Operações síncronas e assíncronasSynchronous and Asynchronous Operations

Este tópico discute como implementar e chamar as operações de serviço assíncronas.This topic discusses implementing and calling asynchronous service operations.

Muitos aplicativos chamam métodos de forma assíncrona porque isso permite que o aplicativo continue a fazer trabalho útil enquanto a chamada do método é executada.Many applications call methods asynchronously because it enables the application to continue doing useful work while the method call runs. Os serviços e clientes do Windows Communication Foundation (WCF) podem participar de chamadas de operações assíncronas em dois níveis diferentes do aplicativo, o que fornece aos aplicativos do WCF ainda mais flexibilidade para maximizar a taxa de transferência balanceada contra interatividade.Windows Communication Foundation (WCF) services and clients can participate in asynchronous operation calls at two distinct levels of the application, which provide WCF applications even more flexibility to maximize throughput balanced against interactivity.

Tipos de operações assíncronasTypes of Asynchronous Operations

Todos os contratos de serviço WCF, independentemente dos tipos de parâmetros e valores retornados, usam os atributos do WCF para especificar um padrão de troca de mensagens específico entre o cliente e o serviço.All service contracts in WCF, no matter the parameters types and return values, use WCF attributes to specify a particular message exchange pattern between client and service. O WCF roteia automaticamente mensagens de entrada e de saída para a operação de serviço apropriada ou o código cliente em execução.WCF automatically routes inbound and outbound messages to the appropriate service operation or running client code.

O cliente possui apenas o contrato de serviço, que especifica o padrão de troca de mensagens para uma operação específica.The client possesses only the service contract, which specifies the message exchange pattern for a particular operation. Os clientes podem oferecer ao desenvolvedor qualquer modelo de programação que escolherem, desde que o padrão subjacente de troca de mensagens seja observado.Clients can offer the developer any programming model they choose, so long as the underlying message exchange pattern is observed. Portanto, os serviços também podem implementar operações de qualquer maneira, desde que o padrão de mensagem especificado seja observado.So, too, can services implement operations in any manner, so long as the specified message pattern is observed.

A independência do contrato de serviço na implementação do serviço ou do cliente permite os seguintes formulários de execução assíncrona em aplicativos do WCF:The independence of the service contract from either the service or client implementation enables the following forms of asynchronous execution in WCF applications:

  • Os clientes podem chamar operações de solicitação/resposta de forma assíncrona usando uma troca de mensagens síncrona.Clients can invoke request/response operations asynchronously using a synchronous message exchange.

  • Os serviços podem implementar uma operação de solicitação/resposta de forma assíncrona usando uma troca de mensagens síncrona.Services can implement a request/response operation asynchronously using a synchronous message exchange.

  • As trocas de mensagens podem ser unidirecionais, independentemente da implementação do cliente ou do serviço.Message exchanges can be one-way, regardless of the implementation of the client or service.

Cenários assíncronos sugeridosSuggested Asynchronous Scenarios

Use uma abordagem assíncrona em uma implementação de operação do serviço se a implementação do serviço da operação fizer uma chamada de bloqueio, como ao executar trabalho de E/S.Use an asynchronous approach in a service operation implementation if the operation service implementation makes a blocking call, such as doing I/O work. Quando você estiver em uma implementação de operação assíncrona, tente chamar operações e métodos assíncronos para estender ao máximo o caminho da chamada assíncrona.When you are in an asynchronous operation implementation, try to call asynchronous operations and methods to extend the asynchronous call path as far as possible. Por exemplo, chame um BeginOperationTwo() de dentro de BeginOperationOne().For example, call a BeginOperationTwo() from within BeginOperationOne().

  • Use uma abordagem assíncrona em um aplicativo cliente ou de chamada nos seguintes casos:Use an asynchronous approach in a client or calling application in the following cases:

  • Se você estiver chamando operações em um aplicativo de camada intermediária.If you are invoking operations from a middle-tier application. (Para saber mais sobre esses cenários, confira Aplicativos cliente de camada intermediária.)(For more information about such scenarios, see Middle-Tier Client Applications.)

  • Se você estiver chamando operações em uma página do ASP.NET, use páginas assíncronas.If you are invoking operations within an ASP.NET page, use asynchronous pages.

  • Se você estiver chamando operações em qualquer aplicativo que seja single-threaded, como o Windows Forms ou o Windows Presentation Foundation (WPF).If you are invoking operations from any application that is single threaded, such as Windows Forms or Windows Presentation Foundation (WPF). Ao usar o modelo de chamada assíncrona com base em eventos, o evento resultante é gerado no thread da interface do usuário, adicionando capacidade de resposta ao aplicativo sem exigir que você mesmo manipule vários threads.When using the event-based asynchronous calling model, the result event is raised on the UI thread, adding responsiveness to the application without requiring you to handle multiple threads yourself.

  • Em geral, se você puder escolher entre uma chamada síncrona e uma chamada assíncrona, escolha a chamada assíncrona.In general, if you have a choice between a synchronous and asynchronous call, choose the asynchronous call.

Implementando uma operação de serviço assíncronaImplementing an Asynchronous Service Operation

As operações assíncronas podem ser implementadas usando um dos três métodos a seguir:Asynchronous operations can be implemented by using one of the three following methods:

  1. O padrão assíncrono baseado em tarefasThe task-based asynchronous pattern

  2. O padrão assíncrono baseado em eventosThe event-based asynchronous pattern

  3. O padrão assíncrono IAsyncResultThe IAsyncResult asynchronous pattern

O padrão assíncrono baseado em tarefasTask-Based Asynchronous Pattern

O padrão assíncrono baseado em tarefas é o modo preferido de implementar operações assíncronas porque é mais fácil e mais simples.The task-based asynchronous pattern is the preferred way to implement asynchronous operations because it is the easiest and most straight forward. Para usar esse método, basta implementar a operação de serviço e especificar um tipo de retorno de tarefa <T> , em que T é o tipo retornado pela operação lógica.To use this method simply implement your service operation and specify a return type of Task<T>, where T is the type returned by the logical operation. Por exemplo:For example:

public class SampleService:ISampleService
{
   // ...  
   public async Task<string> SampleMethodTaskAsync(string msg)
   {
      return Task<string>.Factory.StartNew(() =>
      {
         return msg;
      });
   }  
   // ...  
}  

A operação SampleMethodTaskAsync retorna a tarefa <string> porque a operação lógica retorna uma cadeia de caracteres.The SampleMethodTaskAsync operation returns Task<string> because the logical operation returns a string. Para saber mais sobre o padrão assíncrono baseado em tarefas, confira O padrão assíncrono baseado em tarefas.For more information about the task-based asynchronous pattern, see The Task-Based Asynchronous Pattern.

Aviso

Ao usar o padrão assíncrono baseado em tarefas, uma T: System.AggregateException pode ser gerada se uma exceção ocorrer ao aguardar a conclusão da operação.When using the task-based asynchronous pattern, a T:System.AggregateException may be thrown if an exception occurs while waiting on the completion of the operation. Esta exceção pode ocorrer no cliente ou nos serviçosThis exception may occur on the client or services

O padrão assíncrono baseado em eventosEvent-Based Asynchronous Pattern

Um serviço que dá suporte ao padrão assíncrono baseada em eventos terá uma ou mais operações chamadas MethodNameAsync.A service that supports the Event-based Asynchronous Pattern will have one or more operations named MethodNameAsync. Esses métodos podem espelhar versões síncronas, que realizam a mesma operação no thread atual.These methods may mirror synchronous versions, which perform the same operation on the current thread. A classe também pode ter um evento MethodNameCompleted e pode ter um método MethodNameAsyncCancel (ou simplesmente CancelAsync).The class may also have a MethodNameCompleted event and it may have a MethodNameAsyncCancel (or simply CancelAsync) method. Um cliente que deseja chamar a operação definirá um manipulador de eventos para ser chamado quando a operação for concluída,A client wishing to call the operation will define an event handler to be called when the operation completes,

O snippet de código a seguir ilustra como declarar operações assíncronas usando o padrão assíncrono baseado em eventos.The following code snippet illustrates how to declare asynchronous operations using the event-based asynchronous pattern.

public class AsyncExample  
{  
    // Synchronous methods.  
    public int Method1(string param);  
    public void Method2(double param);  
  
    // Asynchronous methods.  
    public void Method1Async(string param);  
    public void Method1Async(string param, object userState);  
    public event Method1CompletedEventHandler Method1Completed;  
  
    public void Method2Async(double param);  
    public void Method2Async(double param, object userState);  
    public event Method2CompletedEventHandler Method2Completed;  
  
    public void CancelAsync(object userState);  
  
    public bool IsBusy { get; }  
  
    // Class implementation not shown.  
}  

Para saber mais sobre o padrão assíncrono baseado em eventos, confira O padrão assíncrono baseado em eventos.For more information about the Event-based Asynchronous Pattern, see The Event-Based Asynchronous Pattern.

O padrão assíncrono IAsyncResultIAsyncResult Asynchronous Pattern

Uma operação de serviço pode ser implementada de maneira assíncrona usando o padrão de programação assíncrona .NET Framework e marcando o <Begin> método com a AsyncPattern propriedade definida como true .A service operation can be implemented in an asynchronous fashion using the .NET Framework asynchronous programming pattern and marking the <Begin> method with the AsyncPattern property set to true. Nesse caso, a operação assíncrona é exposta nos metadados no mesmo formulário que uma operação síncrona: é exposta como única operação com uma mensagem de solicitação e uma mensagem de resposta correlacionada.In this case, the asynchronous operation is exposed in metadata in the same form as a synchronous operation: It is exposed as a single operation with a request message and a correlated response message. Os modelos de programação do cliente têm uma opção.Client programming models then have a choice. Podem representar esse padrão como uma operação síncrona ou assíncrona, desde que, quando o serviço for chamado, ocorra uma troca de mensagens de solicitação de resposta.They can represent this pattern as a synchronous operation or as an asynchronous one, so long as when the service is invoked a request-response message exchange takes place.

Em geral, com a natureza assíncrona dos sistemas, você não deve usar uma dependência nos threads.In general, with the asynchronous nature of the systems, you should not take a dependency on the threads. A maneira mais confiável de transmitir dados para vários estágios do processamento da expedição da operação é usar extensões.The most reliable way of passing data to various stages of operation dispatch processing is to use extensions.

Para ter um exemplo, confira Como implementar uma operação de serviço assíncrona.For an example, see How to: Implement an Asynchronous Service Operation.

Para definir uma operação X do contrato que é executada de forma assíncrona independentemente de como é chamada no aplicativo cliente:To define a contract operation X that is executed asynchronously regardless of how it is called in the client application:

  • Defina dois métodos usando o padrão BeginOperation e EndOperation.Define two methods using the pattern BeginOperation and EndOperation.

  • O método BeginOperation inclui os parâmetros in e ref para a operação e retorna um tipo IAsyncResult.The BeginOperation method includes in and ref parameters for the operation and returns an IAsyncResult type.

  • O método EndOperation inclui um parâmetro IAsyncResult e também os parâmetros out e ref e retorna o tipo de retorno das operações.The EndOperation method includes an IAsyncResult parameter as well as the out and ref parameters and returns the operations return type.

Por exemplo, consulte o seguinte método.For example, see the following method.

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  

Para criar uma operação assíncrona, os dois métodos seriam:To create an asynchronous operation, the two methods would be:

[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  

Observação

O atributo OperationContractAttribute é aplicado apenas ao método BeginDoWork.The OperationContractAttribute attribute is applied only to the BeginDoWork method. O contrato resultante tem uma operação WSDL denominada DoWork.The resulting contract has one WSDL operation named DoWork.

Chamadas assíncronas do lado do clienteClient-Side Asynchronous Invocations

Um aplicativo cliente do WCF pode usar qualquer um dos três modelos de chamada assíncrona descritos anteriormenteA WCF client application can use any of three asynchronous calling models described previously

Ao usar o modelo baseado em tarefas, basta chamar a operação usando a palavra-chave de espera conforme mostrado no snippet de código a seguir.When using the task-based model, simply call the operation using the await keyword as shown in the following code snippet.

await simpleServiceClient.SampleMethodTaskAsync("hello, world");  

Usar o padrão assíncrono baseado em eventos requer apenas adicionar um manipulador de eventos para receber uma notificação da resposta -- e o evento resultante é gerado automaticamente no thread da interface do usuário.Using the event-based asynchronous pattern only requires adding an event handler to receive a notification of the response -- and the resulting event is raised on the user interface thread automatically. Para usar essa abordagem, especifique as opções de comando /async e /tcv:Version35 com a Ferramenta Utilitário de Metadados ServiceModel (Svcutil.exe), como no exemplo a seguir.To use this approach, specify both the /async and /tcv:Version35 command options with the ServiceModel Metadata Utility Tool (Svcutil.exe), as in the following example.

svcutil http://localhost:8000/servicemodelsamples/service/mex /async /tcv:Version35  

Quando isso é feito, Svcutil.exe gera uma classe de cliente do WCF com a infraestrutura do evento que permite que o aplicativo de chamada implemente e atribua um manipulador de eventos para receber a resposta e executar a ação apropriada.When this is done, Svcutil.exe generates a WCF client class with the event infrastructure that enables the calling application to implement and assign an event handler to receive the response and take the appropriate action. Para ver um exemplo completo, confira Como chamar operações de serviço de forma assíncrona.For a complete example, see How to: Call Service Operations Asynchronously.

No entanto, o modelo assíncrono baseado em evento só está disponível no .NET Framework 3,5.The event-based asynchronous model, however, is only available in .NET Framework 3.5. Além disso, não há suporte para ele mesmo no .NET Framework 3,5 quando um canal de cliente WCF é criado usando um System.ServiceModel.ChannelFactory<TChannel> .In addition, it is not supported even in .NET Framework 3.5 when a WCF client channel is created by using a System.ServiceModel.ChannelFactory<TChannel>. Com objetos de canal de cliente do WCF, você deve usar objetos System.IAsyncResult para chamar suas operações de forma assíncrona.With WCF client channel objects, you must use System.IAsyncResult objects to invoke your operations asynchronously. Para usar essa abordagem, especifique a opção de comando /async com a Ferramenta Utilitário de Metadados ServiceModel (Svcutil.exe), como no exemplo a seguir.To use this approach, specify the /async command option with the ServiceModel Metadata Utility Tool (Svcutil.exe), as in the following example.

svcutil http://localhost:8000/servicemodelsamples/service/mex /async

Isso gera um contrato de serviço no qual cada operação é modelada como um método <Begin> com a propriedade AsyncPattern definida como true e um método <End> correspondente.This generates a service contract in which each operation is modeled as a <Begin> method with the AsyncPattern property set to true and a corresponding <End> method. Para ver um exemplo completo do uso de um ChannelFactory<TChannel>, confira Como chamar operações assíncronas usando uma fábrica de canais.For a complete example using a ChannelFactory<TChannel>, see How to: Call Operations Asynchronously Using a Channel Factory.

Em ambos os casos, os aplicativos podem chamar uma operação de forma assíncrona mesmo que o serviço seja implementado de forma síncrona, da mesma forma que um aplicativo pode usar o mesmo padrão para chamar de forma assíncrona um método síncrono local.In either case, applications can invoke an operation asynchronously even if the service is implemented synchronously, in the same way that an application can use the same pattern to invoke asynchronously a local synchronous method. Como a operação é implementada não é significativo para o cliente. Quando a mensagem de resposta chega, seu conteúdo é expedido para o método <End> assíncrono do cliente e o cliente recupera as informações.How the operation is implemented is not significant to the client; when the response message arrives, its content is dispatched to the client's asynchronous <End> method and the client retrieves the information.

Padrões de troca de mensagens unidirecionalOne-Way Message Exchange Patterns

Você também pode criar um padrão de troca de mensagens assíncronas no qual as operações unidirecionais (operações na quais OperationContractAttribute.IsOneWay é true não têm resposta correlacionada) podem ser enviadas em qualquer direção pelo cliente ou pelo serviço independentemente do outro lado.You can also create an asynchronous message exchange pattern in which one-way operations (operations for which the OperationContractAttribute.IsOneWay is true have no correlated response) can be sent in either direction by the client or service independently of the other side. (Isso usa o padrão de troca de mensagens duplex com mensagens unidirecionais.) Nesse caso, o contrato de serviço especifica uma troca de mensagens unidirecional que o lado pode implementar como chamadas ou implementações assíncronas, ou não, conforme apropriado.(This uses the duplex message exchange pattern with one-way messages.) In this case, the service contract specifies a one-way message exchange that either side can implement as asynchronous calls or implementations, or not, as appropriate. Em geral, quando o contrato é uma troca de mensagens unidirecional, as implementações podem ser amplamente assíncronas porque, depois que uma mensagem é enviada, o aplicativo não espera uma resposta e pode continuar a fazer outro trabalho.Generally, when the contract is an exchange of one-way messages, the implementations can largely be asynchronous because once a message is sent the application does not wait for a reply and can continue doing other work.

Clientes e contratos de mensagens assíncronas com base em eventosEvent-based Asynchronous Clients and Message Contracts

As diretrizes de design do modelo assíncrono baseado em eventos declaram que, se mais de um valor for retornado, um valor será retornado como a propriedade Result e os outros serão retornados como propriedades no objeto EventArgs.The design guidelines for the event-based asynchronous model state that if more than one value is returned, one value is returned as the Result property and the others are returned as properties on the EventArgs object. Um resultado é que, se um cliente importar metadados usando as opções de comando assíncrono com base em eventos, e a operação retornar mais de um valor, o objeto padrão EventArgs retornará um valor como a propriedade Result e os restantes serão propriedades do objeto EventArgs.One result of this is that if a client imports metadata using the event-based asynchronous command options and the operation returns more than one value, the default EventArgs object returns one value as the Result property and the remainder are properties of the EventArgs object.

Se você desejar receber o objeto de mensagem como a propriedade Result e ter valores retornados como propriedades nesse objeto, use a opção de comando /messageContract.If you want to receive the message object as the Result property and have the returned values as properties on that object, use the /messageContract command option. Isso gera uma assinatura que retorna a mensagem de resposta como a propriedade Result no objeto EventArgs.This generates a signature that returns the response message as the Result property on the EventArgs object. Todos os valores de retorno internos são propriedades do objeto da mensagem de resposta.All internal return values are then properties of the response message object.

Confira tambémSee also