如何:使用通道工厂以异步方式调用操作
本主题介绍客户端如何在使用基于 ChannelFactory<TChannel> 的客户端应用程序时以异步方式访问服务操作。 (当使用 System.ServiceModel.ClientBase<TChannel> 对象调用服务时,可以使用事件驱动的异步调用模型。 有关详细信息,请参阅如何:以异步方式调用服务操作。 有关基于事件的异步调用模式的更多信息,请参阅基于事件的异步模式 (EAP)。
本主题中的服务可实现 ICalculator
接口。 客户端可以在此接口上以异步方式调用操作,这意味着像 Add
这样的操作将拆分为两个方法:BeginAdd
和 EndAdd
。前一个方法启动调用,而后一个方法在操作完成时检索结果。 有关如何在服务中异步调用操作的示例,请参阅如何:以异步方式实现服务操作。 有关同步和异步操作的详细信息,请参阅同步和异步操作。
过程
以异步方式调用 WCF 服务操作
运行带有
/async
选项的 ServiceModel 元数据实用工具 (Svcutil.exe),如下面的命令所示。svcutil /n:http://Microsoft.ServiceModel.Samples,Microsoft.ServiceModel.Samples http://localhost:8000/servicemodelsamples/service/mex /a
这将生成该操作的服务协定的异步客户端版本。
创建一个异步操作完成时将要调用的回调函数,如下面的示例代码所示。
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
若要以异步方式访问服务操作,请创建客户端、调用
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({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
)以检索结果。
示例
上面过程中的客户端代码使用的服务可实现 ICalculator
接口,如下面的代码所示。 在服务端,协定的 Add
和 Subtract
操作由 Windows Communication Foundation (WCF) 运行时以同步方式调用,即使前面的客户端步骤是在客户端以异步方式调用的也是如此。 在服务端,Multiply
和 Divide
操作用于在服务端以异步方式调用服务,即使客户端以同步方式调用这两个操作也是如此。 此示例将 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