Interacción remota asincrónica
La programación asincrónica en un escenario de interacción remota es idéntica a la programación asincrónica en un contexto o dominio de una sola aplicación, excepto en la configuración y los requisitos de .NET remoting propiamente dicho. Para obtener un ejemplo completo en el que se utilice .NET remoting y delegados sincrónicos y asincrónicos, vea Ejemplo de interacción remota: Interacción remota asincrónica.
Al igual que con la programación asincrónica en un dominio de una sola aplicación, el uso de la programación asincrónica en un escenario de .NET remoting significa que:
- El llamador decide si una determinada llamada remota es asincrónica.
- Los tipos remotos no tienen que admitir explícitamente el comportamiento asincrónico de sus clientes.
- El motor de tiempo de ejecución impone una total seguridad de tipos.
- Debe usar los objetos System.Threading correctamente para esperar o sincronizar sus métodos.
No obstante, en una aplicación que realiza llamadas más allá de los límites de un dominio de aplicación o de un contexto, .NET remoting requiere configurar el sistema .NET remoting y garantizar que su modelo de programación en el cliente también es válido como destino de una llamada remota. La razón es bien sencilla: si usa llamadas asincrónicas, podrá usar una función de devolución de llamada a la que el sistema .NET remoting llamará desde el servidor. Por ejemplo, si pasa un delegado a un método estático (que no se puede utilizar de forma remota) o si olvida establecer en "0" (cero) un puerto del canal (para permitir que el sistema seleccione un puerto del cliente), su llamada al servidor podrá realizarse pero no podrá obtener de ninguna manera el resultado porque la devolución de llamada a su cliente no llegará a realizarse.
Su cliente no necesita extender MarshalByRefObject ni configurar ningún tipo remoto por sí mismo pero, aparte de eso, debe respetar las mismas reglas que cualquier tipo remoto destinado a ser un servidor:
- Una instancia debe recibir la función de devolución de llamada.
- Un canal debe estar registrado para que escuche la función de devolución de llamada.
Paradigma de programación asincrónica
El proceso para la programación asincrónica es igual de sencillo que el utilizado para un dominio de una sola aplicación:
- Cree una instancia de un objeto que pueda recibir una llamada remota a un método.
- Englobe el método de instancia en un objeto AsyncDelegate.
- Englobe el método remoto en otro delegado.
- Llame al método BeginInvoke en el segundo delegado pasándole todos los argumentos, al objeto AsyncDelegate y a un objeto que contenga el estado (o una referencia nula, Nothing en Visual Basic).
- Espere a que el objeto de servidor llame a su método de devolución de llamada.
Aunque éste es el enfoque general, puede variarlo hasta cierto punto. Si en un momento dado desea esperar a que se devuelva una determinada llamada, tome la interfaz IAsyncResult que devolvió la llamada a BeginInvoke, recupere la instancia WaitHandle para ese objeto y llame al método WaitOne, tal y como se indica en el siguiente ejemplo de código.
Dim RemoteCallback As New AsyncCallback(AddressOf Me.OurCallBack)
Dim RemoteDel As New RemoteAsyncDelegate(AddressOf obj.RemoteMethod)
Dim RemAr As IAsyncResult = RemoteDel.BeginInvoke(RemoteCallback, Nothing)
RemAr.AsyncWaitHandle.WaitOne()
[C#]
AsyncCallback RemoteCallback = new AsyncCallback(this.OurCallBack);
RemoteAsyncDelegate RemoteDel = new RemoteAsyncDelegate(obj.RemoteMethod);
IAsyncResult RemAr = RemoteDel.BeginInvoke(RemoteCallback, null);
RemAr.AsyncWaitHandle.WaitOne();
O bien, espere en un bucle que comprueba si la llamada se ha realizado o mediante primitivas System.Threading como la clase ManualResetEvent y, a continuación, finalice la llamada usted mismo.
Dim RemoteCallback As New AsyncCallback(AddressOf Me.OurCallBack)
Dim RemoteDel As New RemoteAsyncDelegate(AddressOf obj.RemoteMethod)
Dim RemAr As IAsyncResult = RemoteDel.BeginInvoke(RemoteCallback, Nothing)
If RemAr.IsCompleted Then
Dim del As RemoteAsyncDelegate = CType(CType(RemAr, AsyncResult).AsyncDelegate, RemoteAsyncDelegate)
Console.WriteLine(("**SUCCESS**: Result of the remote AsyncCallBack: " _
+ del.EndInvoke(RemAr)))
' Allow the callback thread to interrupt the primary thread to execute the callback.
Thread.Sleep(1)
End If ' Do something.
[C#]
AsyncCallback RemoteCallback = new AsyncCallback(this.OurCallBack);
RemoteAsyncDelegate RemoteDel = new RemoteAsyncDelegate(obj.RemoteMethod);
IAsyncResult RemAr = RemoteDel.BeginInvoke(RemoteCallback, null);
if (RemAr.IsCompleted){
RemoteAsyncDelegate del = (RemoteAsyncDelegate)((AsyncResult) RemAr).AsyncDelegate;
Console.WriteLine("**SUCCESS**: Result of the remote AsyncCallBack: "
+ del.EndInvoke(RemAr) );
// Allow the callback thread to interrupt the primary thread to execute the callback.
Thread.Sleep(1);
}
Por último, puede hacer que su subproceso principal cree un ManualResetEvent y espere la función de devolución de llamada, que entonces indicará el ManualResetEvent como la última línea antes de volver. Para obtener un ejemplo de este tipo de espera, vea los comentarios sobre código fuente en Ejemplo de interacción remota: Interacción remota asincrónica.
Problemas
Observe que si el cliente es una clase enlazada a un contexto que requiere un contexto sincronizado, la función de devolución de llamada se enviará a través de la infraestructura de contextos de .NET remoting. Eso significa que la función de devolución de llamada se puede ejecutar de forma asincrónica con respecto al llamador de estos contextos. El atributo OneWayAttribute también tiene este comportamiento cuando decora firmas de métodos de devolución de llamada. Estas funciones de devolución de llamada al método se pueden ejecutar de forma sincrónica o asincrónica con respecto al llamador remoto, que no puede suponer nada sobre la finalización de este tipo de llamada cuando se le devuelve el control de la ejecución.
Además, el comportamiento de una segunda llamada al método EndInvoke antes de que se realice la operación asincrónica con la misma interfaz IAsyncResult no está definido.
Vea también
Información general de .NET Remoting | Ejemplo de interacción remota: Interacción remota asincrónica | Configuración