Partilhar via


Como chamar operações de forma assíncrona usando uma fábrica de canais

Este tópico aborda como um cliente pode acessar uma operação de serviço de forma assíncrona ao usar um aplicativo cliente baseado em ChannelFactory<TChannel>. (Ao usar um objeto System.ServiceModel.ClientBase<TChannel> para invocar um serviço, você pode usar o modelo de chamada assíncrona controlado por eventos. Para obter mais informações, consulte Como realizar chamadas a operações de serviço de forma assíncrona. Para obter mais informações sobre o modelo de chamada assíncrona baseada em evento, consulte Padrão assíncrono baseado em evento (EAP).)

O serviço neste tópico implementa a interface ICalculator. 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 dos quais inicia a chamada e o segundo recupera o resultado quando a operação é concluída. Para obter um exemplo mostrando como implementar uma operação de forma assíncrona em um serviço, consulte Como implementar uma operação de serviço assíncrona. Para obter detalhes sobre operações síncronas e assíncronas, consulte Synchronous and Asynchronous Operations.

Tramitação processual

Para efetuar chamadas assíncronas às operações de serviço WCF

  1. Execute a ferramenta ServiceModel Metadata Utility Tool (Svcutil.exe) com a opção /async, conforme mostrado no comando a seguir.

    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.

  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.

    static void AddCallback(IAsyncResult ar)
    {
        double result = ((CalculatorClient)ar.AsyncState).EndAdd(ar);
        Console.WriteLine($"Add Result: {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.

    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({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.

Exemplo

O serviço usado com o código do cliente usado no procedimento anterior implementa a interface ICalculator, conforme mostrado no código a seguir. No lado do serviço, as operações Add e Subtract do contrato são chamadas de forma síncrona pelo runtime do Windows Communication Foundation (WCF), mesmo que as etapas anteriores no cliente sejam chamadas de forma assíncrona. As operações Multiply e Divide são usadas para invocar o serviço de forma assíncrona no lado do serviço, mesmo que o cliente as invoque de forma síncrona. Este exemplo define a propriedade AsyncPattern como true. Essa configuração de propriedade, em combinação com a implementação do padrão assíncrono do .NET Framework, informa ao tempo de execução para invocar a operação de forma assíncrona.

[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