作法:使用通道處理站以非同步方式呼叫作業
本主題涵蓋用戶端如何能夠在使用 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
這會針對作業的服務合約產生非同步用戶端版本。
建立要在非同步作業完成時呼叫的回呼函式 (Callback Function),如下列範例程式碼所示。
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