如何使用通道工厂异步调用操作

本主题介绍客户端在使用基于ChannelFactory<TChannel>的客户端应用程序时如何异步访问服务操作。 (使用 System.ServiceModel.ClientBase<TChannel> 对象调用服务时,可以使用事件驱动的异步调用模型。 有关详细信息,请参阅 如何:异步调用服务操作。 有关基于事件的异步调用模型的详细信息,请参阅 基于事件的异步模式(EAP)。

本主题中的服务实现 ICalculator 接口。 客户端可以异步调用此接口上的操作,这意味着类似 Add 的操作被拆分为两种方法,前者 BeginAdd 启动调用,而后者 EndAdd 在操作完成时检索结果。 有关如何在服务中异步实现作的示例,请参阅 如何:实现异步服务作。 有关同步和异步作的详细信息,请参阅 同步和异步作

Procedure

异步调用 WCF 服务操作

  1. 使用以下命令中所示的选项运行 /async 工具。

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

    这会为操作生成服务契约的异步客户端版本。

  2. 创建在异步作完成时要调用的回调函数,如以下示例代码所示。

    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. 若要异步访问服务作,请创建客户端并调用 Begin[Operation] (例如 BeginAdd),并指定回调函数,如以下示例代码所示。

    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)
    

    执行回调函数时,客户端将调用 End<operation> (例如), EndAdd以检索结果。

Example

与上述过程中使用的客户端代码一起使用的服务实现 ICalculator 接口,如以下代码所示。 在服务端,AddSubtract合约的操作由 Windows Communication Foundation(WCF)在运行时同步调用,即使在之前的客户端步骤是异步调用的。 MultiplyDivide操作用于在服务端异步调用服务,即使客户端同步调用服务也是如此。 本示例将 AsyncPattern 属性设置为 true. 此属性设置与 .NET Framework 异步模式的实现相结合,告知运行时异步调用操作。

[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