このトピックでは、 ChannelFactory<TChannel> ベースのクライアント アプリケーションを使用するときに、クライアントがサービス操作に非同期的にアクセスする方法について説明します。 ( System.ServiceModel.ClientBase<TChannel> オブジェクトを使用してサービスを呼び出す場合は、イベント ドリブン非同期呼び出しモデルを使用できます。 詳細については、「 方法: サービス操作を非同期的に呼び出す」を参照してください。 イベント ベースの非同期呼び出しモデルの詳細については、「 イベント ベースの非同期パターン (EAP)」を参照してください。
このトピックのサービスでは、 ICalculator
インターフェイスを実装します。 クライアントは、このインターフェイスの操作を非同期的に呼び出すことができます。つまり、 Add
などの操作は、 BeginAdd
と EndAdd
の 2 つのメソッドに分割され、前者は呼び出しを開始し、後者は操作の完了時に結果を取得します。 サービスに非同期的に操作を実装する方法を示す例については、「 方法: 非同期サービス操作を実装する」を参照してください。 同期操作と非同期操作の詳細については、「 同期操作と非同期操作」を参照してください。
プロシージャ
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: {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({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