Comunicazione remota asincrona

In uno scenario remoto la programmazione asincrona è identica a quella in un singolo contesto o dominio applicazione, ad eccezione della configurazione e dei requisiti del sistema .NET Remoting. Per un esempio completo in cui si utilizzano .NET Remoting e delegati sincroni e asincroni, vedere Esempio di comunicazione remota: comunicazione remota asincrona.

Come nella programmazione asincrona in un dominio applicazione singolo, l'utilizzo della programmazione asincrona in uno scenario .NET Remoting comporta quanto segue.

  • Il chiamante decide se una determinata chiamata remota è asincrona.
  • Non occorre che i tipi remoti supportino in modo esplicito il comportamento asincrono tramite i rispettivi client.
  • Nel runtime si applica la completa indipendenza dai tipi.
  • È necessario utilizzare correttamente gli oggetti System.Threading per attendere o sincronizzare i metodi.

In un'applicazione in cui si effettuano chiamate oltre i limiti di contesto o dominio applicazione, tuttavia, è necessario configurare il sistema .NET Remoting e assicurarsi che il modello di programmazione client sia anche qualificato come destinazione per una chiamata remota. Il motivo è semplice: se si utilizzano chiamate asincrone, sarà possibile utilizzare una funzione di callback che verrà richiamata dal server mediante il sistema .NET Remoting. Se, ad esempio, un delegato viene passato a un metodo static che non può essere utilizzato in modalità remota o se si dimentica di impostare su "0" una porta per il canale in modo da consentire al sistema di selezionare una porta client, la chiamata al server potrebbe essere completata, ma non sarà possibile ottenere il risultato in quanto il callback al client non verrà completato.

Non occorre che il client estenda MarshalByRefObject o configuri tipi remoti, ma per il resto deve seguire le stesse regole applicabili a qualsiasi tipo remoto destinato a rappresentare un server.

  • La funzione di callback deve essere ricevuta da un'istanza.
  • È necessario registrare un canale per attendere la funzione di callback.

Paradigma di programmazione asincrona

Il processo di programmazione asincrona è semplice come quello per un singolo dominio applicazione.

  1. Creare un'istanza di un oggetto in grado di ricevere una chiamata remota a un metodo.
  2. Utilizzare un oggetto AsyncDelegate come wrapper di tale metodo di istanza.
  3. Utilizzare un altro delegato come wrapper del metodo remoto.
  4. Chiamare il metodo BeginInvoke sul secondo delegato, passando gli argomenti, AsyncDelegate e alcuni oggetti per mantenere lo stato (o un riferimento null, Nothing in Visual Basic).
  5. Attendere che l'oggetto server chiami il metodo di callback.

Questo approccio generale può essere modificato in parte. Se in qualsiasi momento si desidera attendere la restituzione di una determinata chiamata, è sufficiente accettare l'interfaccia IAsyncResult restituita dalla chiamata di BeginInvoke, recuperare l'istanza di WaitHandle per tale oggetto e chiamare il metodo WaitOne, come illustrato nell'esempio di codice riportato di seguito.

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();

In alternativa, è possibile attendere in un ciclo che consente di controllare se la chiamata è stata completata o utilizzando primitive System.Threading come la classe ManualResetEvent, quindi terminare la chiamata.

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);
}

Infine, è possibile far sì che il thread principale crei un oggetto ManualResetEvent e attenda la funzione di callback, la quale segnala quindi tale oggetto come ultima riga prima del completamento. Per un esempio di questo tipo di attesa, vedere i commenti al codice sorgente in Esempio di comunicazione remota: comunicazione remota asincrona.

Problemi

Se il client è una classe associata al contesto che richiede un contesto sincronizzato, la funzione di callback viene inviata attraverso l'infrastruttura del contesto di .NET Remoting. La funzione di callback stessa può pertanto essere eseguita in modo asincrono relativamente al proprio chiamante per tali contesti. Tale comportamento è uguale a quello dell'attributo OneWayAttribute nella decorazione delle firme dei metodi di callback. Qualsiasi funzione di callback di metodo può essere eseguita in modo sincrono o asincrono relativamente al chiamante remoto e quest'ultimo non può avanzare supposizioni sul completamento di tale chiamata quando gli viene restituito il controllo di esecuzione.

Inoltre, la chiamata al metodo EndInvoke prima che l'operazione asincrona venga completata una seconda volta con la stessa interfaccia IAsyncResult non è definita.

Vedere anche

Cenni preliminari su .NET Remoting | Esempio di comunicazione remota: comunicazione remota asincrona | Configurazione