次の方法で共有


方法: 非同期サービス操作を実装する

Windows Communication Foundation (WCF) アプリケーションでは、サービス操作を非同期または同期的に実装できます。クライアントに呼び出し方法を指示する必要はありません。 たとえば、非同期サービス操作は同期的に呼び出すことができます。同期サービス操作は非同期的に呼び出すことができます。 クライアント アプリケーションで操作を非同期的に呼び出す方法を示す例については、「 方法: サービス操作を非同期的に呼び出す」を参照してください。 同期操作と非同期操作の詳細については、「 サービス コントラクトの設計 」および「 同期および非同期操作」を参照してください。 このトピックでは、非同期サービス操作の基本的な構造について説明します。コードは完全ではありません。 サービス側とクライアント側の両方の完全な例については、「 非同期」を参照してください。

サービス操作を非同期的に実装する

  1. サービス コントラクトで、.NET 非同期設計ガイドラインに従って非同期メソッド ペアを宣言します。 Begin メソッドは、パラメーター、コールバック オブジェクト、および状態オブジェクトを受け取り、System.IAsyncResultを受け取って戻り値を返すEndと一致するSystem.IAsyncResult メソッドを返します。 非同期呼び出しの詳細については、「 非同期プログラミング設計パターン」を参照してください。

  2. 非同期メソッド ペアの Begin メソッドを System.ServiceModel.OperationContractAttribute 属性でマークし、 OperationContractAttribute.AsyncPattern プロパティを true に設定します。 たとえば、次のコードは手順 1 と 2 を実行します。

      [OperationContractAttribute(AsyncPattern=true)]
      IAsyncResult BeginServiceAsyncMethod(string msg, AsyncCallback callback, object asyncState);
    
      // Note: There is no OperationContractAttribute for the end method.
      string EndServiceAsyncMethod(IAsyncResult result);
    }
    
        <OperationContractAttribute(AsyncPattern:=True)> _
        Function BeginServiceAsyncMethod(ByVal msg As String, ByVal callback As AsyncCallback, ByVal asyncState As Object) As IAsyncResult
    
        ' Note: There is no OperationContractAttribute for the end method.
        Function EndServiceAsyncMethod(ByVal result As IAsyncResult) As String
    End Interface
    
  3. 非同期設計ガイドラインに従って、サービス クラスに Begin/End メソッド ペアを実装します。 たとえば、次のコード例は、非同期サービス操作の Begin 部分と End 部分の両方で文字列がコンソールに書き込まれ、 End 操作の戻り値がクライアントに返される実装を示しています。 完全なコード例については、「例」セクションを参照してください。

    public IAsyncResult BeginServiceAsyncMethod(string msg, AsyncCallback callback, object asyncState)
    {
      Console.WriteLine($"BeginServiceAsyncMethod called with: \"{msg}\"");
      return new CompletedAsyncResult<string>(msg);
    }
    
    public string EndServiceAsyncMethod(IAsyncResult r)
    {
      CompletedAsyncResult<string> result = r as CompletedAsyncResult<string>;
      Console.WriteLine($"EndServiceAsyncMethod called with: \"{result.Data}\"");
      return result.Data;
    }
    
    Public Function BeginServiceAsyncMethod(ByVal msg As String, ByVal callback As AsyncCallback, ByVal asyncState As Object) As IAsyncResult Implements ISampleService.BeginServiceAsyncMethod
        Console.WriteLine("BeginServiceAsyncMethod called with: ""{0}""", msg)
        Return New CompletedAsyncResult(Of String)(msg)
    End Function
    
    Public Function EndServiceAsyncMethod(ByVal r As IAsyncResult) As String Implements ISampleService.EndServiceAsyncMethod
        Dim result As CompletedAsyncResult(Of String) = TryCast(r, CompletedAsyncResult(Of String))
        Console.WriteLine("EndServiceAsyncMethod called with: ""{0}""", result.Data)
        Return result.Data
    End Function
    

次のコード例を示します。

  1. インターフェイスを持つサービス契約:

    1. 同期 SampleMethod 操作。

    2. 非同期 BeginSampleMethod 操作。

    3. 非同期 BeginServiceAsyncMethod/EndServiceAsyncMethod 操作のペア。

  2. System.IAsyncResult オブジェクトを使用したサービス実装。

using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Text;
using System.Threading;

namespace Microsoft.WCF.Documentation
{
  [ServiceContractAttribute(Namespace="http://microsoft.wcf.documentation")]
  public interface ISampleService{

    [OperationContractAttribute]
    string SampleMethod(string msg);

    [OperationContractAttribute(AsyncPattern = true)]
    IAsyncResult BeginSampleMethod(string msg, AsyncCallback callback, object asyncState);

    //Note: There is no OperationContractAttribute for the end method.
    string EndSampleMethod(IAsyncResult result);

    [OperationContractAttribute(AsyncPattern=true)]
    IAsyncResult BeginServiceAsyncMethod(string msg, AsyncCallback callback, object asyncState);

    // Note: There is no OperationContractAttribute for the end method.
    string EndServiceAsyncMethod(IAsyncResult result);
  }

  public class SampleService : ISampleService
  {
    #region ISampleService Members

    public string  SampleMethod(string msg)
    {
      Console.WriteLine($"Called synchronous sample method with \"{msg}\"");
        return "The synchronous service greets you: " + msg;
    }

    // This asynchronously implemented operation is never called because
    // there is a synchronous version of the same method.
    public IAsyncResult BeginSampleMethod(string msg, AsyncCallback callback, object asyncState)
    {
      Console.WriteLine("BeginSampleMethod called with: " + msg);
      return new CompletedAsyncResult<string>(msg);
    }

    public string EndSampleMethod(IAsyncResult r)
    {
      CompletedAsyncResult<string> result = r as CompletedAsyncResult<string>;
      Console.WriteLine("EndSampleMethod called with: " + result.Data);
      return result.Data;
    }

    public IAsyncResult BeginServiceAsyncMethod(string msg, AsyncCallback callback, object asyncState)
    {
      Console.WriteLine($"BeginServiceAsyncMethod called with: \"{msg}\"");
      return new CompletedAsyncResult<string>(msg);
    }

    public string EndServiceAsyncMethod(IAsyncResult r)
    {
      CompletedAsyncResult<string> result = r as CompletedAsyncResult<string>;
      Console.WriteLine($"EndServiceAsyncMethod called with: \"{result.Data}\"");
      return result.Data;
    }
    #endregion
  }

  // Simple async result implementation.
  class CompletedAsyncResult<T> : IAsyncResult
  {
    T data;

    public CompletedAsyncResult(T data)
    { this.data = data; }

    public T Data
    { get { return data; } }

    #region IAsyncResult Members
    public object AsyncState
    { get { return (object)data; } }

    public WaitHandle AsyncWaitHandle
    { get { throw new Exception("The method or operation is not implemented."); } }

    public bool CompletedSynchronously
    { get { return true; } }

    public bool IsCompleted
    { get { return true; } }
    #endregion
  }
}

Imports System.Collections.Generic
Imports System.ServiceModel
Imports System.Text
Imports System.Threading

Namespace Microsoft.WCF.Documentation
    <ServiceContractAttribute(Namespace:="http://microsoft.wcf.documentation")> _
    Public Interface ISampleService

        <OperationContractAttribute> _
        Function SampleMethod(ByVal msg As String) As String

        <OperationContractAttribute(AsyncPattern:=True)> _
        Function BeginSampleMethod(ByVal msg As String, ByVal callback As AsyncCallback, ByVal asyncState As Object) As IAsyncResult

        'Note: There is no OperationContractAttribute for the end method.
        Function EndSampleMethod(ByVal result As IAsyncResult) As String

        <OperationContractAttribute(AsyncPattern:=True)> _
        Function BeginServiceAsyncMethod(ByVal msg As String, ByVal callback As AsyncCallback, ByVal asyncState As Object) As IAsyncResult

        ' Note: There is no OperationContractAttribute for the end method.
        Function EndServiceAsyncMethod(ByVal result As IAsyncResult) As String
    End Interface

    Public Class SampleService
        Implements ISampleService
#Region "ISampleService Members"

        Public Function SampleMethod(ByVal msg As String) As String Implements ISampleService.SampleMethod
            Console.WriteLine("Called synchronous sample method with ""{0}""", msg)
            Return "The synchronous service greets you: " & msg
        End Function

        ' This asynchronously implemented operation is never called because
        ' there is a synchronous version of the same method.
        Public Function BeginSampleMethod(ByVal msg As String, ByVal callback As AsyncCallback, ByVal asyncState As Object) As IAsyncResult Implements ISampleService.BeginSampleMethod
            Console.WriteLine("BeginSampleMethod called with: " & msg)
            Return New CompletedAsyncResult(Of String)(msg)
        End Function

        Public Function EndSampleMethod(ByVal r As IAsyncResult) As String Implements ISampleService.EndSampleMethod
            Dim result As CompletedAsyncResult(Of String) = TryCast(r, CompletedAsyncResult(Of String))
            Console.WriteLine("EndSampleMethod called with: " & result.Data)
            Return result.Data
        End Function

        Public Function BeginServiceAsyncMethod(ByVal msg As String, ByVal callback As AsyncCallback, ByVal asyncState As Object) As IAsyncResult Implements ISampleService.BeginServiceAsyncMethod
            Console.WriteLine("BeginServiceAsyncMethod called with: ""{0}""", msg)
            Return New CompletedAsyncResult(Of String)(msg)
        End Function

        Public Function EndServiceAsyncMethod(ByVal r As IAsyncResult) As String Implements ISampleService.EndServiceAsyncMethod
            Dim result As CompletedAsyncResult(Of String) = TryCast(r, CompletedAsyncResult(Of String))
            Console.WriteLine("EndServiceAsyncMethod called with: ""{0}""", result.Data)
            Return result.Data
        End Function
#End Region
    End Class

    ' Simple async result implementation.
    Friend Class CompletedAsyncResult(Of T)
        Implements IAsyncResult
        Private data_Renamed As T

        Public Sub New(ByVal data As T)
            Me.data_Renamed = data
        End Sub

        Public ReadOnly Property Data() As T
            Get
                Return data_Renamed
            End Get
        End Property

#Region "IAsyncResult Members"
        Public ReadOnly Property AsyncState() As Object Implements IAsyncResult.AsyncState
            Get
                Return CObj(data_Renamed)
            End Get
        End Property

        Public ReadOnly Property AsyncWaitHandle() As WaitHandle Implements IAsyncResult.AsyncWaitHandle
            Get
                Throw New Exception("The method or operation is not implemented.")
            End Get
        End Property

        Public ReadOnly Property CompletedSynchronously() As Boolean Implements IAsyncResult.CompletedSynchronously
            Get
                Return True
            End Get
        End Property

        Public ReadOnly Property IsCompleted() As Boolean Implements IAsyncResult.IsCompleted
            Get
                Return True
            End Get
        End Property
#End Region
    End Class
End Namespace

こちらも参照ください