方法: チャネル ファクトリを使用して、非同期的に操作を呼び出すHow to: Call Operations Asynchronously Using a Channel Factory

ここでは、ChannelFactory<TChannel> ベースのクライアント アプリケーションを使用する場合に、クライアントからサービス操作に非同期にアクセスする方法について説明します。This topic covers how a client can access a service operation asynchronously when using a ChannelFactory<TChannel>-based client application. サービスを呼び出すために System.ServiceModel.ClientBase<TChannel> オブジェクトを使用する場合は、イベント ドリブンの非同期呼び出しモデルを使用できます。(When using a System.ServiceModel.ClientBase<TChannel> object to invoke a service you can use the event-driven asynchronous calling model. 詳細については、「方法: サービス操作を非同期に呼び出す」を参照してください。For more information, see How to: Call Service Operations Asynchronously. イベントベースの非同期呼び出しモデルの詳細については、「イベントベースの非同期パターン (EAP)」を参照してください。For more information about the event-based asynchronous calling model, see Event-based Asynchronous Pattern (EAP).)

このトピックのサービスは、ICalculator インターフェイスを実装しています。The service in this topic implements the ICalculator interface. クライアントはこのインターフェイスにある操作を非同期に呼び出すことができます。これはたとえば Add という操作を BeginAddEndAdd の 2 つのメソッドに分割できることを意味します。前者によって呼び出しを開始し、後者によって操作の完了時に結果を取得します。The client can call the operations on this interface asynchronously, which means that operations like Add are split into two methods, BeginAdd and EndAdd, the former of which initiates the call and the latter of which retrieves the result when the operation completes. サービスで操作を非同期に実装する方法を示す例については、「方法: 非同期サービス操作を実装する」を参照してください。For an example showing how to implement an operation asynchronously in a service, see How to: Implement an Asynchronous Service Operation. 同期操作と非同期操作の詳細については、「同期操作と非同期操作」を参照してください。For details about synchronous and asynchronous operations, see Synchronous and Asynchronous Operations.

手順Procedure

WCF サービス操作を非同期に呼び出すにはTo call WCF service operations asynchronously

  1. 次のコマンドに示すように、オプションを指定してServiceModel メタデータユーティリティツール (svcutil.exe)ツールを実行し /async ます。Run the ServiceModel Metadata Utility Tool (Svcutil.exe) tool with the /async option as shown in the following command.

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

    これにより、操作の非同期クライアント版のサービス コントラクトが生成されます。This generates an asynchronous client version of the service contract for the operation.

  2. 次のサンプル コードに示すように、非同期操作の完了時に呼び出されるコールバック関数を作成します。Create a callback function to be called when the asynchronous operation is complete, as shown in the following sample code.

    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
    
  3. サービス操作に非同期にアクセスするには、次のサンプル コードに示すように、クライアントを作成して Begin[Operation] (たとえば BeginAdd) を呼び出し、コールバック関数を指定します。To access a service operation asynchronously, create the client and call the Begin[Operation] (for example, BeginAdd) and specify a callback function, as shown in the following sample code.

    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 など) を呼び出して結果を取得します。When the callback function executes, the client calls End<operation> (for example, EndAdd) to retrieve the result.

Example

上記の手順で使用したクライアント コードで使用するサービスは、次のコードに示すように ICalculator インターフェイスを実装しています。The service that is used with the client code that is used in the preceding procedure implements the ICalculator interface as shown in the following code. サービス側では、 Add Subtract 前のクライアントの手順がクライアント上で非同期に呼び出されている場合でも、コントラクトの操作と操作は、WINDOWS COMMUNICATION FOUNDATION (WCF) の実行時によって同期的に呼び出されます。On the service side, the Add and Subtract operations of the contract are invoked synchronously by the Windows Communication Foundation (WCF) run time, even though the preceding client steps are invoked asynchronously on the client. Multiply 操作と Divide 操作は、クライアントで同期して呼び出される場合でも、サービス側ではサービスを非同期に呼び出すように使用されます。The Multiply and Divide operations are used to invoke the service asynchronously on the service side, even if the client invokes them synchronously. この例では、AsyncPattern プロパティを true に設定します。This example sets the AsyncPattern property to true. このプロパティ設定は、.NET Framework 非同期パターンの実装と組み合わせて、操作を非同期的に呼び出すように実行時に指示します。This property setting, in combination with the implementation of the .NET Framework asynchronous pattern, tells the run time to invoke the operation asynchronously.

[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