Поделиться через


Как асинхронно вызывать операции с использованием фабрики каналов

В этой теме описывается, каким образом клиент может асинхронно обратиться к операции службы при использовании клиентского приложения, основанного на ChannelFactory. (При вызове службы с помощью объекта System.ServiceModel.ClientBase можно использовать управляемую событиями модель асинхронных вызовов. Дополнительные сведения см. в разделе Как асинхронно вызывать операции службы WCF. Дополнительные сведения об управляемой событиями модели асинхронного вызова см. в разделе Multithreaded Programming with the Event-based Asynchronous Pattern.)

Служба в этом разделе реализует интерфейс ICalculator. Клиент может асинхронно вызвать операции для этого интерфейса, это означает, что операции типа Add разделяются на два метода, BeginAdd и EndAdd, первый из них инициирует вызов, а второй извлекает результат после завершения операции. Пример, в котором показана реализация асинхронной операции в службе, см. в разделе Как асинхронно реализовывать операции службы. Дополнительные сведения о синхронных и асинхронных операциях см. в разделе Синхронные и асинхронные операции.

Процедура

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

  1. Запустите средство Служебное средство ServiceModel Metadata Utility Tool (Svcutil.exe) с параметром /async, как показано в следующей команде.

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

    Результатом станет создание асинхронной версии клиента контракта службы для операции.

  2. Создайте функцию обратного вызова, вызываемую после завершения асинхронной операции, как показано в следующем примере кода.

    Private Shared Sub AddCallback(ByVal ar As IAsyncResult)
        Dim result = (CType(ar.AsyncState, CalculatorClient)).EndAdd(ar)
        Console.WriteLine("Add Result: {0}", result)
    End Sub
    
    static void AddCallback(IAsyncResult ar)
    {
        double result = ((CalculatorClient)ar.AsyncState).EndAdd(ar);
        Console.WriteLine("Add Result: {0}", result);
    }
    
  3. Чтобы асинхронно обратиться к операции службы, создайте клиент и вызовите Begin[Operation] (например BeginAdd) и задайте функцию обратного вызова, как показано в следующем примере кода.

    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)
    
    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);
    

    При выполнении функции обратного вызова клиент вызывает End<operation> (например EndAdd), чтобы извлечь результат.

Пример

Служба, используемая с клиентским кодом, который применяется в предыдущей процедуре, реализует интерфейс ICalculator, как показано в следующем коде. На стороне службы операции контракта Add и Subtract вызываются синхронно во время выполнения Windows Communication Foundation (WCF), даже если на предыдущих этапах клиента выполнялся асинхронный вызов для клиента. Операции Multiply и Divide используются для асинхронного вызова службы на стороне службы, даже если клиент вызывает их синхронно. В этом примере свойству AsyncPattern присваивается значение true. Этот параметр свойства в сочетании с реализацией асинхронной модели .NET Framework сообщает среде выполнения о необходимости асинхронного вызова операции.

<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
[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);
}

См. также

Задачи

Асинхронное взаимодействие