Практическое руководство. Асинхронный вызов операций с использованием фабрики каналовHow to: Call Operations Asynchronously Using a Channel Factory

В этой теме описывается, каким образом клиент может асинхронно обратиться к операции службы при использовании клиентского приложения, основанного на ChannelFactory<TChannel>.This topic covers how a client can access a service operation asynchronously when using a ChannelFactory<TChannel>-based client application. (При вызове службы с помощью объекта System.ServiceModel.ClientBase<TChannel> можно использовать управляемую событиями модель асинхронных вызовов.(When using a System.ServiceModel.ClientBase<TChannel> object to invoke a service you can use the event-driven asynchronous calling model. Дополнительные сведения см. в разделе инструкции. асинхронный вызов операций службы.For more information, see How to: Call Service Operations Asynchronously. Дополнительные сведения о модели асинхронного вызова на основе событий см. в разделе асинхронная модель на основе событий (EAP).For more information about the event-based asynchronous calling model, see Event-based Asynchronous Pattern (EAP).)

Служба в этом разделе реализует интерфейс ICalculator.The service in this topic implements the ICalculator interface. Клиент может асинхронно вызвать операции для этого интерфейса, это означает, что операции типа Add разделяются на два метода, BeginAdd и EndAdd, первый из них инициирует вызов, а второй извлекает результат после завершения операции.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. Пример, демонстрирующий асинхронную реализацию операции в службе, см. в разделе как реализовать асинхронную операцию службы.For an example showing how to implement an operation asynchronously in a service, see How to: Implement an Asynchronous Service Operation. Дополнительные сведения о синхронных и асинхронных операциях см. в разделе синхронные и асинхронные операции.For details about synchronous and asynchronous operations, see Synchronous and Asynchronous Operations.

ПроцедураProcedure

Асинхронный вызов операций службы WCFTo call WCF service operations asynchronously

  1. Запустите средство служебной программы метаданных ServiceModel (Svcutil.exe) с /async параметром, как показано в следующей команде.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  
    

    Результатом станет создание асинхронной версии клиента контракта службы для операции.This generates an asynchronous client version of the service contract for the operation.

  2. Создайте функцию обратного вызова, вызываемую после завершения асинхронной операции, как показано в следующем примере кода.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. Чтобы асинхронно обратиться к операции службы, создайте клиент и вызовите Begin[Operation] (например BeginAdd) и задайте функцию обратного вызова, как показано в следующем примере кода.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)
    

    При выполнении функции обратного вызова клиент вызывает End<operation> (например EndAdd), чтобы извлечь результат.When the callback function executes, the client calls End<operation> (for example, EndAdd) to retrieve the result.

ПримерExample

Служба, используемая с клиентским кодом, который применяется в предыдущей процедуре, реализует интерфейс ICalculator, как показано в следующем коде.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. На стороне службы Add операции и в Subtract контракте вызываются синхронно с помощью Windows Communication Foundation (WCF) времени выполнения, хотя предыдущие этапы клиента вызываются на клиенте асинхронно.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. Операции Multiply и Divide используются для асинхронного вызова службы на стороне службы, даже если клиент вызывает их синхронно.The Multiply and Divide operations are used to invoke the service asynchronously on the service side, even if the client invokes them synchronously. В этом примере свойству AsyncPattern присваивается значение true.This example sets the AsyncPattern property to true. Этот параметр свойства в сочетании с реализацией асинхронного шаблона платформа .NET Framework сообщает времени выполнения о необходимости асинхронного вызова операции.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