次の方法で共有


非同期 XML Web サービス メソッドの作成

長時間実行され、スレッドをブロックするメソッドを呼び出す XML Web サービス メソッドのパフォーマンスを向上させるには、XML Web サービス メソッドを非同期 XML Web サービス メソッドとして公開します。非同期 XML Web サービス メソッドを実装すると、スレッドがスレッド プールに返されたときに、他のコードを実行できます。これによって、スレッド プール内の限られた数のスレッドをもう 1 回実行でき、システムの全体的なパフォーマンスとスケーラビリティが向上します。

一般的に、I/O 操作を実行するメソッドを呼び出す XML Web サービス メソッドは、非同期的な実装に適しています。このようなメソッドの例としては、他の XML Web サービスと通信するメソッド、リモート データベースにアクセスするメソッド、ネットワーク I/O を実行するメソッド、およびサイズの大きいファイルを読み書きするメソッドがあります。これらのメソッドはすべて、その大部分の時間をハードウェアでの実行に費やし、XML Web サービス メソッドを実行するスレッドはブロックされたままになります。XML Web サービス メソッドが非同期的に実装されている場合、このスレッドを解放して他のコードを実行できます。

XML Web サービス メソッドが非同期的に実装されているかどうかに関係なく、クライアントは XML Web サービス メソッドと非同期通信を実行できます。XML Web サービス メソッドが同期的に実装されている場合でも、Web サービス記述言語ツール (WSDL.EXE) によって生成されたプロキシ クラスで、.NET クライアントに非同期通信が公開されます。このプロキシ クラスには、各 XML Web サービス メソッドとの非同期通信を行うための Begin メソッドと End メソッドが含まれています。したがって、XML Web サービス メソッドを非同期的に実装するか、同期的に実装するかの判断は、パフォーマンスに基づいて行う必要があります。

メモ   非同期 XML Web サービス メソッドを実装しても、クライアントと、XML Web サービスを管理するホストとの間の HTTP 接続には影響しません。HTTP 接続は切断されず、プールもされません。

非同期 XML Web サービス メソッドを実装するには

非同期 XML Web サービス メソッドの実装は、.NET Framework の非同期デザイン パターンに従います。

  1. 同期 XML Web サービス メソッドを 2 つのメソッドに分割します。この 2 つは基本名が同じで、一方の名前は Begin で始まり、もう一方の名前は End で始まります。

  2. Begin メソッドのパラメータ リストには、メソッドの機能で使用するすべての in パラメータと by reference パラメータが含まれ、2 つのパラメータが最後に追加されています。

    • By reference パラメータは in パラメータと同様に指定します。
    • 最後から 2 番目のパラメータは AsyncCallback である必要があります。AsyncCallback パラメータによって、クライアントはデリゲートを提供できます。このデリゲートは、メソッドが完了したときに呼び出されます。非同期 XML Web サービス メソッドが別の非同期メソッドを呼び出す場合は、AsyncCallback パラメータをこのメソッドの最後から 2 番目のパラメータに渡すことができます。
    • 最後のパラメータは Object です。Object パラメータによって、呼び出し元はメソッドに状態情報を提供できます。非同期 XML Web サービス メソッドが別の非同期メソッドを呼び出す場合は、Object パラメータをこのメソッドの最後のパラメータに渡すことができます。
    • 戻り値は IAsyncResult 型である必要があります。

    メソッドの機能に固有の String パラメータを含む Begin メソッドのコード例を次に示します。

    [WebMethod]
    public IAsyncResult BeginGetAuthorRoyalties(String Author,
                      AsyncCallback callback, object asyncState) 
    [Visual Basic]
    <WebMethod()> _
    Public Function BeginGetAuthorRoyalties(ByVal Author As String, _
       ByVal callback As AsyncCallback, ByVal asyncState As Object) _
                        As IAsyncResult
    
  3. End メソッドのパラメータ リストは、IAsyncResult と、これに続くメソッドの機能に固有の out パラメータと by reference パラメータで構成されます。

    • 戻り値は、同期 XML Web サービス メソッドの戻り値と同じ型です。
    • By reference パラメータは out パラメータと同様に指定します。

    AuthorRoyalties ユーザー定義型を返す End メソッドのコード例を次に示します。

    [WebMethod]
    public AuthorRoyalties EndGetAuthorRoyalties(IAsyncResult
                                       asyncResult)
    [Visual Basic]
    <WebMethod()> _
    Public Function EndGetAuthorRoyalties(ByVal asyncResult As _
                        IAsyncResult) As AuthorRoyalties
    

    別の XML Web サービス メソッドと非同期通信する XML Web サービス メソッドのコード例を次に示します。

    using System;
    using System.Web.Services;
    
    [WebService(Namespace="https://www.contoso.com/")]
    public class MyService : WebService {
      public RemoteService remoteService;
      public MyService() {
         // Create a new instance of proxy class for 
         // the XML Web service to be called.
         remoteService = new RemoteService();
      }
      // Define the Begin method.
      [WebMethod]
      public IAsyncResult BeginGetAuthorRoyalties(String Author,
                      AsyncCallback callback, object asyncState) {
         // Begin asynchronous communictation with a different XML Web
         // service.
         return remoteService.BeginReturnedStronglyTypedDS(Author,
                             callback,asyncState);
      }
      // Define the End method.
      [WebMethod]
      public AuthorRoyalties EndGetAuthorRoyalties(IAsyncResult
                                       asyncResult) {
       // Return the asynchronous result from the other XML Web service.
       return remoteService.EndReturnedStronglyTypedDS(asyncResult);
      }
    }
    [Visual Basic]
    Imports System.Web.Services
    <WebService(Namespace:="https://www.contoso.com/")> _
    Public Class MyService
       Inherits WebService
       Public remoteService As RemoteService
    
       Public Sub New()
          MyBase.New()
          ' Create a new instance of proxy class for 
          ' the XML Web service to be called.
          remoteService = New RemoteService()
       End Sub
    
       ' Define the Begin method.
       <WebMethod()> _
       Public Function BeginGetAuthorRoyalties(ByVal Author As String, _
       ByVal callback As AsyncCallback, ByVal asyncState As Object) _
                        As IAsyncResult
          ' Begin asynchronous communictation with a different XML Web
          ' service.
          Return remoteService.BeginReturnedStronglyTypedDS(Author, _
                                callback, asyncState)
       End Function
       ' Define the End method.
       <WebMethod()> _
       Public Function EndGetAuthorRoyalties(ByVal asyncResult As _
                        IAsyncResult) As AuthorRoyalties
          ' Return the asynchronous result from the other XML Web service.
          Return remoteService.EndReturnedStronglyTypedDS(asyncResult)
       End Function
    End Class
    

XML Web サービス メソッドが複数の非同期呼び出しを実行し、その呼び出しを順に実行する必要がある場合に、非同期呼び出しをチェイン処理する方法を次のコード例に示します。BeginGetAuthorRoyalties メソッドは、渡された作成者が有効であるかどうかを調べる非同期呼び出しを実行し、AuthorRoyaltiesCallback という名前の中間的なコールバックを設定して結果を受け取ります。作成者が有効である場合、この中間的なコールバックは非同期呼び出しを実行して、その作成者の印税の値を取得します。

using System.Web.Services;
using System.Data;
using System;
// This imports the proxy class for the XML Web services
// that the sample communicates with.
using AsyncWS.localhost;

namespace AsyncWS
{
    [WebService(Namespace="https://www.contoso.com/")]
    public class MyService : System.Web.Services.WebService
    {
        public RemoteService remoteService;
        public MyService()
        {
           remoteService = new RemoteService();
        }

        [WebMethod]
        public IAsyncResult BeginGetAuthorRoyalties(String Author,
               AsyncCallback callback, Object asyncState) 
       {
          // Saves the current state for the call that gets the author's
          // royalties.
          AsyncStateChain state = new AsyncStateChain();
          state.originalState = asyncState;
          state.Author = Author;
          state.originalCallback = callback;

          // Creates an intermediary callback.
          AsyncCallback chainedCallback = new
             AsyncCallback(AuthorRoyaltiesCallback);
          return remoteService.BeginGetAuthors(chainedCallback,state);
       }
       // Intermediate method to handle chaining the 
       // asynchronous calls.
       public void AuthorRoyaltiesCallback(IAsyncResult ar)
       {
          AsyncStateChain state = (AsyncStateChain)ar.AsyncState;
          RemoteService rs = new RemoteService();

          // Gets the result from the call to GetAuthors.
          Authors allAuthors = rs.EndGetAuthors(ar);

          Boolean found = false;
          // Verifies that the requested author is valid.
          int i = 0;
          DataRow row;
          while (i < allAuthors.authors.Rows.Count && !found)
          {
             row = allAuthors.authors.Rows[i];
             if (row["au_lname"].ToString() == state.Author) 
             {
                found = true;
             }
             i++;
          }
          if (found)
          {
             AsyncCallback cb = state.originalCallback;
             // Calls the second XML Web service, because the author is
             // valid.
             rs.BeginReturnedStronglyTypedDS(state.Author,cb,state);
          }
          else
          {
            // Cannot throw the exception in this function or the XML Web
            // service will hang. So, set the state argument to the
            // exception and let the End method of the chained XML Web
            // service check for it.  
            ArgumentException ex = new ArgumentException(
              "Author does not exist.","Author");
            AsyncCallback cb = state.originalCallback;
            // Call the second XML Web service, setting the state to an
            // exception.
            rs.BeginReturnedStronglyTypedDS(state.Author,cb,ex);
          }
       }

       [WebMethod]
       public AuthorRoyalties EndGetAuthorRoyalties(IAsyncResult
                                                    asyncResult) 
       {
        // Check whehter the first XML Web service threw an exception.
        if (asyncResult.AsyncState is ArgumentException)
          throw (ArgumentException) asyncResult.AsyncState;
        else
         return remoteService.EndReturnedStronglyTypedDS(asyncResult);
       }
    }
    // Class to wrap the callback and state for the intermediate
    // asynchronous operation.
    public class AsyncStateChain 
    {
       public AsyncCallback originalCallback;
       public Object originalState;
       public String Author;
    }
}
[Visual Basic]
Imports System.Web.Services
Imports System.Data
Imports System
' This imports the proxy class for the XML Web services
' that the sample communicates with.
Imports AsyncWS_VB.localhost


Namespace AsyncWs

<WebService(Namespace:="https://www.contoso.com/")> _
Public Class MyService
    Inherits WebService
    Public remoteService As remoteService
    Public Sub New()
        MyBase.New()
        remoteService = New localhost.RemoteService()
    End Sub
    ' Defines the Begin method.
    <WebMethod()> _
    Public Function BeginGetAuthorRoyalties(ByVal Author As String, _
    ByVal callback As AsyncCallback, ByVal asyncState As Object) _
                    As IAsyncResult
        ' Saves the current state for the call that gets the author's
        ' royalties.
        Dim state As AsyncStateChain = New AsyncStateChain()
        state.originalState = asyncState
        state.Author = Author
        state.originalCallback = callback

        ' Creates an intermediary callback.
        Dim chainedCallback As AsyncCallback = New AsyncCallback( _
           AddressOf AuthorRoyaltiesCallback)
        ' Begin asynchronous communictation with a different XML Web
        ' service.
        Return remoteService.BeginGetAuthors(chainedCallback, state)
    End Function

    ' Intermediate method to handle chaining the asynchronous calls.
    Public Sub AuthorRoyaltiesCallback(ByVal ar As IAsyncResult)
        Dim state As AsyncStateChain = CType(ar.AsyncState, _
            AsyncStateChain)
        Dim rs As RemoteService = New RemoteService()

        ' Gets the result from the call to GetAuthors.
        Dim allAuthors As Authors = rs.EndGetAuthors(ar)
        Dim found As Boolean = False

        ' Verifies that the requested author is valid.
        Dim i As Integer = 0
        Dim row As DataRow
        While (i < allAuthors.authors.Rows.Count And (Not found))
            row = allAuthors.authors.Rows(i)
            If (row("au_lname").ToString() = state.Author) Then
                found = True
            End If
            i = i + 1
        End While
        If (found) Then
            Dim cb As AsyncCallback = state.originalCallback
            ' Calls the second XML Web service, because the author is
            ' valid.
            rs.BeginReturnedStronglyTypedDS(state.Author, cb, state)
        Else
          ' Cannot throw the exception in this function or the XML Web
          ' service will hang.  So, set the state argument to the
          ' exception and let the End method of the chained XML Web
          ' service check for it.  
            Dim ex As ArgumentException = New ArgumentException( _ 
                "Author does not exist.", "Author")
            Dim cb As AsyncCallback = state.originalCallback
            ' Call the second XML Web service, setting the state to an
            ' exception.
            rs.BeginReturnedStronglyTypedDS(state.Author, cb, ex)
        End If
    End Sub

    ' Define the End method.
    <WebMethod()> _
    Public Function EndGetAuthorRoyalties(ByVal asyncResult As _
            IAsyncResult) As localhost.AuthorRoyalties
        ' Return the asynchronous result from the other XML Web service.
        Return remoteService.EndReturnedStronglyTypedDS(asyncResult)
    End Function

End Class

' Class to wrap the callback and state for the intermediate asynchronous
' operation.
Public Class AsyncStateChain
   Public originalCallback As AsyncCallback
   Public originalState As Object
   Public Author As String
End Class
End Namespace

参照

XML Web サービスとの非同期通信 | 非同期呼び出しの組み込み | ASP.NET を使用した XML Web サービスの作成