Operazioni sincrone e asincrone
Vengono descritte le implementazioni e le chiamate asincrone locali e viene illustrato l'utilizzo sincrono di scambi di messaggi asincroni.
Molte applicazioni chiamano metodi in modo asincrono, poiché ciò consente all'applicazione di continuare a eseguire operazioni utili mentre viene effettuata la chiamata al metodo. I servizi e i client Windows Communication Foundation (WCF) possono partecipare alle chiamate di operazioni asincrone a due livelli distinti dell'applicazione, sistema che assicura alle applicazioni WCF ulteriore flessibilità, per ottimizzare la velocità effettiva bilanciata a fronte dell'interattività.
Tipi di operazioni asincrone
Tutti i contratti di servizio in WCF, indipendentemente dai tipi di parametri e dai valori restituiti, utilizzano attributi WCF per specificare un particolare modello di scambio dei messaggi tra client e servizio. WCF indirizza automaticamente i messaggi in ingresso e in uscita all'operazione del servizio appropriata o al codice client di esecuzione.
Il client possiede solo il contratto di servizio, che specifica il modello di scambio dei messaggi per una particolare operazione. I client possono offrire allo sviluppatore qualsiasi modello di programmazione desiderato, purché venga rispettato il modello di scambio dei messaggi sottostante. Anche i servizi possono quindi implementare le operazioni in qualsiasi modo, purché venga rispettato il modello dei messaggi specificato.
L'indipendenza del contratto di servizio dall'implementazione del client o del servizio consente le forme seguenti di esecuzione asincrona nelle applicazioni WCF:
- I client possono richiamare operazioni di richiesta/risposta in modo asincrono utilizzando uno scambio di messaggi sincrono.
- I servizi possono implementare operazioni di richiesta/risposta in modo asincrono utilizzando uno scambio di messaggi sincrono.
- Gli scambi di messaggi possono essere unidirezionali, indipendentemente dall'implementazione del client o del servizio.
Scenari asincroni suggeriti
Utilizzare un approccio asincrono nell'implementazione di un'operazione di servizio se tale implementazione effettua una chiamata di blocco, ad esempio effettuando le operazioni di I/O. Quando si effettua l'implementazione di un'operazione asincrona, provare a chiamare i metodi e le operazioni asincrone per estendere il più possibile il percorso della chiamata asincrona. Ad esempio chiamare l'opzioneBeginOperationTwo()
dall'interno di BeginOperationOne()
.
- Utilizzare un approccio asincrono in un'applicazione client o in un'applicazione chiamante nei seguenti casi:
- Se si richiamano operazioni da un'applicazione di livello intermedio. Per ulteriori informazioni su tali scenari, vedere Applicazioni client di livello intermedio.
- Se si richiamano operazioni all'interno di una pagina ASP.NET, utilizzare pagine asincrone.
- Se si richiamano operazioni da applicazioni a thread singolo, ad esempio Windows Forms o Windows Presentation Foundation (WPF). Se si utilizza il modello di chiamata asincrono basato su eventi, l'evento risultante viene generato sul thread UI, aggiungendo velocità di risposta all'applicazione senza che vi sia necessità di gestire più thread.
- Generalmente, se è possibile scegliere tra una chiamata sincrona e una asincrona, scegliere la seconda.
Chiamate asincrone lato client
Un'applicazione client WCF può utilizzare uno dei due modelli di chiamata asincroni, entrambi descritti in Asynchronous Programming Design Patterns:
- Operazioni asincrone che utilizzano eventi.
- Operazioni asincrone che utilizzano oggetti System.IAsyncResult.
Il primo approccio, il modello asincrono basato su eventi, è consigliabile per le applicazioni chiamanti perchè richiede solamente l'aggiunta di un gestore eventi per ricevere una notifica di risposta -- e l'evento risultante viene automaticamente generato sul thread dell'interfaccia utente. Per utilizzare questo approccio, specificare le opzioni di comando /async e /tcv:Version35 con lo ServiceModel Metadata Utility Tool (Svcutil.exe), come nell'esempio seguente.
svcutil https://localhost:8000/servicemodelsamples/service/mex /async /tcv:Version35
Al termine di questa operazione, Svcutil.exe genera una classe client WCF in cui l'infrastruttura dell'evento consente all'applicazione chiamante di implementare e fare in modo che un gestore eventi riceva la risposta ed esegua le operazioni necessarie. Per un esempio completo, vedere Procedura: chiamare operazioni del servizio WCF in modo asincrono.
Il modello asincrono basato su eventi è disponibile solamente in .NET Framework versione 3.5 Inoltre, non è supportato anche in .NET Framework 3.5 se viene creato un canale client WCF utilizzando la classe System.ServiceModel.ChannelFactory. Con gli oggetti del canale client WCF è necessario utilizzare gli oggetti System.IAsyncResult per richiamare le operazioni in modo asincrono. Per utilizzare questo approccio, specificare l'opzione di comando /async con lo ServiceModel Metadata Utility Tool (Svcutil.exe), come nell'esempio seguente.
svcutil https://localhost:8000/servicemodelsamples/service/mex /async
In questo modo viene generato un contratto di servizio nel quale ciascuna operazione viene modellata come un metodo <Begin>, con la proprietà AsyncPattern impostata su true, e un metodo <End> corrispondente. Per un esempio completo utilizzando una classe ChannelFactory, vedere Procedura: chiamare le operazioni in modo asincrono tramite una channel factory.
In ogni caso, le applicazioni possono richiamare un'operazione in modo asincrono anche se il servizio viene implementato in modo sincrono, esattamente come un'applicazione può utilizzare lo stesso modello per richiamare in modo asincrono un metodo sincrono locale. La modalità di implementazione dell'operazione non è importante per il client; quando il messaggio di risposta arriva, il relativo contenuto viene inviato al metodo asincrono del client <End> e il client recupera le informazioni.
Implementazioni di operazioni asincrone
Allo stesso modo, un'operazione del servizio può essere implementata in modo asincrono utilizzando il modello di programmazione asincrona di .NET Framework e contrassegnando il metodo <Begin> con la proprietà AsyncPattern impostata su true. In questo caso, l'operazione asincrona viene esposta nei metadati nella stessa forma di un'operazione sincrona, ovvero come singola operazione con un messaggio di richiesta e un messaggio di risposta correlato. I modelli di programmazione client possono quindi effettuare una scelta. Possono rappresentare questo modello come operazione sincrona o asincrona, a condizione che, quando viene richiamato il servizio, si verifichi uno scambio di messaggi di richiesta-risposta.
Per un esempio, vedere Procedura: implementare un'operazione del servizio asincrona.
Per definire un'operazione di contratto X
, eseguita in modo asincrono indipendentemente dalla modalità con cui viene chiamata nell'applicazione client:
- Definire due metodi utilizzando il modello BeginOperation e EndOperation.
- Il metodo BeginOperation include i parametri in e out per l'operazione e restituisce un tipo IAsyncResult.
- Il metodo EndOperation include un parametro IAsyncResult, nonché i parametri in e out, e restituisce il tipo restituito dall'operazione.
Vedere, ad esempio, il metodo seguente.
int DoWork(string data, ref string inout, out string outonly)
Function DoWork(ByVal data As String, ByRef inout As String, _
out outonly As out) As Integer
Per creare un'operazione asincrona, i due metodi sarebbero:
[OperationContract(AsyncPattern=true)]
IAsyncResult BeginDoWork(string data,
ref string inout,
AsyncCallback callback,
object state);
int EndDoWork(ref string inout, out string outonly, IAsyncResult result);
<OperationContract(AsyncPattern := True)> _
Function BeginDoWork(ByVal data As String, _
ByRef inout As String, _
ByVal callback As AsyncCallback, _
ByVal state As Object) _
As IAsyncResult
Function EndDoWork(ByRef inout As String, _
ByRef outonly As String, _
ByVal result As IAsyncResult) _
As Integer
Nota
L'attributo OperationContractAttribute viene applicato solo al metodo BeginDoWork
. Il contratto risultante include un'operazione WSDL denominata DoWork
.
Modelli di scambio di messaggi unidirezionali
È inoltre possibile creare un modello di scambio di messaggi asincrono, in cui le operazioni unidirezionali (operazioni per cui se la proprietà System.ServiceModel.OperationContractAttribute.IsOneWay è true non esiste una risposta correlata) possono essere inviate in entrambe le direzioni dal client o dal servizio in modo indipendente dall'altro lato. A tale scopo si utilizza il modello di scambio di messaggi duplex con messaggi unidirezionali. In questo caso, il contratto di servizio specifica uno scambio di messaggi unidirezionale che entrambi i lati possono implementare o meno come chiamate o implementazioni asincrone, in base alle necessità. In genere, quando il contratto è uno scambio di messaggi unidirezionali, le implementazioni sono prevalentemente sincrone, poiché, una volta inviato un messaggio, l'applicazione non attende una risposta e può continuare svolgere la propria funzione.
Contratti client e di messaggio asincroni basati su eventi
Le linee guida di progettazione per il modello asincrono basato su eventi indicano che, se vengono restituiti più valori, un valore viene restituito come proprietà Result e i restanti valori sono restituiti come proprietà nell’oggetto EventArgs. Di conseguenza, è possibile che, se un client importa metadati utilizzando le opzioni di comando asincrone basate su eventi e l'operazione restituisce più valori, l'oggetto predefinito EventArgs restituisce un valore come proprietà Result e i restanti valori come proprietà dell’oggetto EventArgs.
Se si desidera ricevere l'oggetto del messaggio come proprietà Result e i valori restituiti come proprietà in tale oggetto, utilizzare l'opzione di comando /messageContract. Questa operazione genera una firma che restituisce il messaggio di risposta come proprietà Result nell’oggetto EventArgs. Pertanto, tutti i valori restituiti interni sono proprietà dell’oggetto del messaggio di risposta.