Partager via


Création de méthodes de service Web XML asynchrones

Pour améliorer les performances des méthodes de service Web XML appelant des méthodes longues qui bloquent leur thread, pensez à les exposer en tant que méthodes de service Web XML asynchrones. L'implémentation d'une méthode de service Web XML asynchrone permet à ce thread d'exécuter un autre code lorsqu'il est retourné au pool de threads. Cela permet l'exécution d'un thread de plus que le nombre autorisé dans le pool de threads, ce qui améliore les performances et l'évolutivité du système.

En général, les méthodes de service Web XML appelant des méthodes qui exécutent des opérations d'E/S se prêtent très bien à une implémentation asynchrone. Ces méthodes sont, par exemple, celles qui communiquent avec d'autres services Web XML, qui accèdent à des bases de données distantes, qui effectuent des E/S réseau et enfin celles qui lisent et écrivent dans des fichiers volumineux. Toutes ces méthodes passent la majeure partie de leur temps à s'exécuter dans le matériel, ce qui laisse bloqué le thread exécutant la méthode de service Web XML. Ce thread peut être libéré pour exécuter un autre code si la méthode de service Web XML est implémentée de façon asynchrone.

Qu'une méthode de service Web XML soit implémentée de façon asynchrone ou non, les clients peuvent communiquer avec elle dans ce mode. Le communication asynchrone est exposée aux client .NET dans la classe proxy générée par l'outil de langage WSDL (WSDL.EXE), même si une méthode de service Web XML est implémentée de façon synchrone. La classe proxy contient les méthodes Begin et End pour communiquer avec chaque méthode de service Web XML de façon asynchrone. La décision d'implémenter une méthode de service Web XML de façon asynchrone ou synchrone doit donc être prise en tenant compte des performances.

Remarque   L'implémentation d'une méthode de service Web XML asynchrone n'a pas d'incidence sur la connexion HTTP entre le client et le serveur hébergeant le service Web XML. La connexion HTTP n'est ni fermée ni regroupée.

Pour implémenter une méthode de service Web XML asynchrone

L'implémentation d'une méthode de service Web XML asynchrone suit le modèle de design asynchrone du .NET Framework.

  1. Divisez une méthode de service Web XML synchrone en deux méthodes ; attribuez-leur le même nom de base commençant dans un cas par Begin et dans l'autre par End.

  2. La liste de paramètres de la méthode Begin contient tous les paramètres in et by reference nécessaires aux fonctionnalités de la méthode, ainsi que deux autres, ajoutés à la fin.

    • Les paramètres By reference apparaissent dans la liste comme des paramètres in.
    • L'avant-dernier paramètre doit être un paramètre AsyncCallback. Le paramètre AsyncCallback permet au client de fournir un délégué qui est appelé lorsque la méthode s'achève. Lorsqu'une méthode de service Web XML asynchrone appelle une autre méthode asynchrone, ce paramètre peut être passé dans l'avant-dernier paramètre pour cette méthode.
    • Le dernier paramètre est un Object. Le paramètre Object permet à un appelant de fournir à la méthode des informations d'état. Lorsqu'une méthode de service Web XML asynchrone appelle une autre méthode asynchrone, il peut être passé dans le dernier paramètre pour cette méthode.
    • La valeur de retour doit être de type IAsyncResult.

    L'exemple de code suivant est une méthode Begin dotée d'un paramètre String spécifique à ses fonctionnalités.

    [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. La liste de paramètres de la méthode End est constituée de IAsyncResult suivi de tous les paramètres out et by reference spécifiques aux fonctionnalités de la méthode.

    • La valeur de retour a le même type que celle d'une méthode de service Web XML synchrone.
    • Les paramètres By reference apparaissent dans la liste comme des paramètres out.

    L'exemple de code suivant est une méthode End qui retourne un type défini par l'utilisateur AuthorRoyalties.

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

    L'exemple de code suivant est une méthode de service Web XML asynchrone qui communique de façon asynchrone avec une autre méthode de service Web XML.

    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
    

L'exemple de code suivant montre comment chaîner des appels asynchrones lorsqu'une méthode de service Web XML effectue plusieurs appels asynchrones et que ceux-ci doivent s'exécuter séquentiellement. La méthode BeginGetAuthorRoyalties effectue un appel asynchrone pour déterminer si l'auteur passé est valide et configure un rappel intermédiaire appelé AuthorRoyaltiesCallback pour recevoir les résultats. Ce rappel intermédiaire effectue alors un appel asynchrone pour obtenir les droits d'auteur de cet auteur, si celui-ci est valide.

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

Voir aussi

Communication asynchrone avec les services Web XML | Inclusion des appels asynchrones | Création de services Web XML à l'aide d'ASP.NET