Como: chamar operações assíncronas usando uma fábrica de canaisHow to: Call Operations Asynchronously Using a Channel Factory

Este tópico aborda como um cliente pode acessar uma operação de serviço de forma assíncrona ao usar um ChannelFactory<TChannel> aplicativo cliente baseado em um.This topic covers how a client can access a service operation asynchronously when using a ChannelFactory<TChannel>-based client application. (Ao usar um System.ServiceModel.ClientBase<TChannel> objeto para invocar um serviço, você pode usar o modelo de chamada assíncrona orientado por evento.(When using a System.ServiceModel.ClientBase<TChannel> object to invoke a service you can use the event-driven asynchronous calling model. Para obter mais informações, consulte como: chamar operações de serviço de forma assíncrona.For more information, see How to: Call Service Operations Asynchronously. Para obter mais informações sobre o modelo de chamada assíncrona baseado em evento, consulte padrão assíncrono baseado em evento (EAP).)For more information about the event-based asynchronous calling model, see Event-based Asynchronous Pattern (EAP).)

O serviço neste tópico implementa a ICalculator interface.The service in this topic implements the ICalculator interface. O cliente pode chamar as operações nessa interface de forma assíncrona, o que significa que operações como Add são divididas em dois métodos, BeginAdd e EndAdd o primeiro deles inicia a chamada e a última que recupera o resultado quando a operação é concluída.The client can call the operations on this interface asynchronously, which means that operations like Add are split into two methods, BeginAdd and EndAdd, the former of which initiates the call and the latter of which retrieves the result when the operation completes. Para obter um exemplo que mostra como implementar uma operação de forma assíncrona em um serviço, consulte como implementar uma operação de serviço assíncrono.For an example showing how to implement an operation asynchronously in a service, see How to: Implement an Asynchronous Service Operation. Para obter detalhes sobre as operações síncronas e assíncronas, consulte operações síncronas eassíncronas.For details about synchronous and asynchronous operations, see Synchronous and Asynchronous Operations.

ProcedimentoProcedure

Para chamar operações do serviço WCF de forma assíncronaTo call WCF service operations asynchronously

  1. Execute a ferramenta ferramenta de utilitário de metadados ServiceModel (Svcutil.exe) com a /async opção conforme mostrado no comando a seguir.Run the ServiceModel Metadata Utility Tool (Svcutil.exe) tool with the /async option as shown in the following command.

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

    Isso gera uma versão de cliente assíncrona do contrato de serviço para a operação.This generates an asynchronous client version of the service contract for the operation.

  2. Crie uma função de retorno de chamada a ser chamada quando a operação assíncrona for concluída, conforme mostrado no código de exemplo a seguir.Create a callback function to be called when the asynchronous operation is complete, as shown in the following sample code.

    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. Para acessar uma operação de serviço de forma assíncrona, crie o cliente e chame o Begin[Operation] (por exemplo, BeginAdd ) e especifique uma função de retorno de chamada, conforme mostrado no código de exemplo a seguir.To access a service operation asynchronously, create the client and call the Begin[Operation] (for example, BeginAdd) and specify a callback function, as shown in the following sample code.

    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 a função de retorno de chamada é executada, o cliente chama End<operation> (por exemplo, EndAdd ) para recuperar o resultado.When the callback function executes, the client calls End<operation> (for example, EndAdd) to retrieve the result.

ExemploExample

O serviço usado com o código do cliente que é usado no procedimento anterior implementa a ICalculator interface, conforme mostrado no código a seguir.The service that is used with the client code that is used in the preceding procedure implements the ICalculator interface as shown in the following code. No lado do serviço, as Add Subtract operações e do contrato são invocadas de forma síncrona pelo tempo de execução do Windows Communication Foundation (WCF), mesmo que as etapas do cliente precedentes sejam invocadas de modo assíncrono no cliente.On the service side, the Add and Subtract operations of the contract are invoked synchronously by the Windows Communication Foundation (WCF) run time, even though the preceding client steps are invoked asynchronously on the client. As Multiply Divide operações e são usadas para invocar o serviço de forma assíncrona no lado do serviço, mesmo que o cliente os invoque de maneira síncrona.The Multiply and Divide operations are used to invoke the service asynchronously on the service side, even if the client invokes them synchronously. Este exemplo define a AsyncPattern propriedade como true .This example sets the AsyncPattern property to true. Essa configuração de propriedade, em combinação com a implementação do padrão .NET Framework assíncrono, informa o tempo de execução para invocar a operação de forma assíncrona.This property setting, in combination with the implementation of the .NET Framework asynchronous pattern, tells the run time to invoke the operation asynchronously.

[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