Procedura: chiamare le operazioni in modo asincrono tramite una channel factory

In questo argomento viene illustrato in che modo un client può accedere a un'operazione del servizio in modalità asincrona quando si usa un'applicazione client basata su ChannelFactory<TChannel>. Quando si usa un oggetto System.ServiceModel.ClientBase<TChannel> per richiamare un servizio, è possibile usare il modello di chiamata asincrono basato su eventi. Per altre informazioni, vedere Procedura: Chiamare operazioni del servizio in modo asincrono. Per altre informazioni sul modello di chiamata asincrona basato su eventi, vedere Modello asincrono basato su eventi (EAP).

Il servizio in questo argomento implementa l'interfaccia ICalculator. Il client può chiamare in modo asincrono le operazioni su tale interfaccia, il che significa che le operazioni come Add vengono suddivise in due metodi, BeginAdd ed EndAdd, il primo dei quali avvia la chiamata e il secondo recupera il risultato al termine dell'operazione. Per un esempio che illustra come implementare un'operazione in modo asincrono in un servizio, vedere Procedura: Implementare un'operazione asincrona del servizio. Per informazioni dettagliate sulle operazioni sincrone e asincrone, vedere Operazioni sincrone e asincrone.

Procedura

Per chiamare operazioni del servizio WCF in modo asincrono

  1. Eseguire lo strumento ServiceModel Metadata Utility (Svcutil.exe) con l'opzione /async, come illustrato nel comando seguente.

    svcutil /n:http://Microsoft.ServiceModel.Samples,Microsoft.ServiceModel.Samples http://localhost:8000/servicemodelsamples/service/mex /a
    

    Questo genera una versione client asincrona del contratto di servizio per l'operazione.

  2. Creare una funzione di callback da chiamare al temine dell'operazione asincrona, come illustrato nel codice di esempio seguente.

    static void AddCallback(IAsyncResult ar)
    {
        double result = ((CalculatorClient)ar.AsyncState).EndAdd(ar);
        Console.WriteLine("Add Result: {0}", result);
    }
    
    Private Shared Sub AddCallback(ByVal ar As IAsyncResult)
        Dim result = (CType(ar.AsyncState, CalculatorClient)).EndAdd(ar)
        Console.WriteLine("Add Result: {0}", result)
    End Sub
    
  3. Per accedere in modo asincrono a un'operazione del servizio, creare il client, chiamare Begin[Operation] (ad esempio, BeginAdd) e specificare una funzione di callback, come illustrato nel codice di esempio seguente.

    ChannelFactory<ICalculatorChannel> factory = new ChannelFactory<ICalculatorChannel>();
    ICalculatorChannel channelClient = factory.CreateChannel();
    
    // BeginAdd
    double value1 = 100.00D;
    double value2 = 15.99D;
    
    IAsyncResult arAdd = channelClient.BeginAdd(value1, value2, AddCallback, channelClient);
    Console.WriteLine("Add({0},{1})", value1, value2);
    
    Dim factory As New ChannelFactory(Of ICalculatorChannel)()
    Dim channelClient As ICalculatorChannel = factory.CreateChannel()
    
    ' BeginAdd
    Dim value1 = 100.0R
    Dim value2 = 15.99R
    
    Dim arAdd As IAsyncResult = channelClient.BeginAdd(value1, value2, AddressOf AddCallback, channelClient)
    Console.WriteLine("Add({0},{1})", value1, value2)
    

    Quando la funzione di callback viene eseguita, il client chiama End<operation>EndAdd (ad esempio, ) per recuperare il risultato.

Esempio

Il servizio usato con il codice client della procedura precedente implementa l'interfaccia ICalculator come illustrato nel codice seguente. Sul lato del servizio, le operazioni Add e Subtract del contratto vengono richiamate in modo sincrono dal runtime WCF (Windows Communication Foundation), anche se i passaggi client precedenti vengono richiamati in modo asincrono sul client. Le operazioni Multiply e Divide vengono usate per richiamare il servizio in modo asincrono sul lato del servizio, anche se il client le richiama in modo sincrono. In questo esempio la proprietà AsyncPattern viene impostata su true. Tale impostazione della proprietà, in combinazione con l'implementazione del modello asincrono di .NET Framework, consente al runtime di richiamare in modo asincrono l'operazione.

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
    [OperationContract]
    double Add(double n1, double n2);

    [OperationContract]
    double Subtract(double n1, double n2);

    //Multiply involves some file I/O so we'll make it Async.
    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginMultiply(double n1, double n2, AsyncCallback callback, object state);
    double EndMultiply(IAsyncResult ar);

    //Divide involves some file I/O so we'll make it Async.
    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginDivide(double n1, double n2, AsyncCallback callback, object state);
    double EndDivide(IAsyncResult ar);
}
<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples")> _
Public Interface ICalculator
    <OperationContract> _
    Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double

    <OperationContract> _
    Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double

    'Multiply involves some file I/O so we'll make it Async.
    <OperationContract(AsyncPattern:=True)> _
    Function BeginMultiply(ByVal n1 As Double, ByVal n2 As Double, ByVal callback As AsyncCallback, ByVal state As Object) As IAsyncResult
    Function EndMultiply(ByVal ar As IAsyncResult) As Double

    'Divide involves some file I/O so we'll make it Async.
    <OperationContract(AsyncPattern:=True)> _
    Function BeginDivide(ByVal n1 As Double, ByVal n2 As Double, ByVal callback As AsyncCallback, ByVal state As Object) As IAsyncResult
    Function EndDivide(ByVal ar As IAsyncResult) As Double
End Interface