Compartir a través de


Crear métodos de servicio Web XML asincrónicos

Para mejorar el rendimiento de los métodos de servicio Web XML que llaman a métodos de larga duración que bloquean su subproceso, se debe considerar la posibilidad de exponerlos como métodos de servicio Web XML asincrónicos. Al implementar un método de servicio Web XML asincrónico ese subproceso puede ejecutar otro código cuando se devuelve al grupo de subprocesos. Esto permite que se ejecute uno más del número limitado de subprocesos en el grupo, con lo que se mejora el rendimiento y la escalabilidad global del sistema.

En general, los métodos de servicio Web XML que llaman a métodos que realizan operaciones de E/S son buenos candidatos para la implementación asincrónica. Como ejemplos se pueden incluir los métodos que establecen comunicación con otros servicios Web XML, los que tienen acceso a bases de datos remotas, los que realizan E/S de red, así como los métodos que se utilizan para leer y escribir en archivos de gran tamaño. Estos métodos emplean gran parte de su tiempo en ejecutar hardware, lo cual bloquea al subproceso que ejecuta el método de servicio Web XML. Se puede liberar ese subproceso para que ejecute otro código si el método de servicio Web XML se implementa de forma asincrónica.

Independientemente de si se implementa un método de servicio Web XML de forma asincrónica, los clientes pueden comunicarse con él de forma asincrónica. La comunicación asincrónica se expone a los clientes .NET en la clase de proxy generada por la herramienta Lenguaje de descripción de servicios Web (WSDL.EXE), aunque un método de servicio Web XML se implemente sincrónicamente. La clase de proxy contiene los métodos Begin y End para la comunicación asincrónica con cada método de servicio Web XML. Por tanto, la decisión de implementar un método de servicio Web XML de forma asincrónica o sincrónica debe basarse en el rendimiento.

Nota   La implementación de un método de servicio Web XML asincrónico no repercute en la conexión HTTP entre el cliente y el servidor que aloja el servicio Web XML. La conexión HTTP ni se cierra ni se agrupa.

Para implementar un método de servicio Web XML asincrónico

La implementación de un método de servicio Web XML asincrónico sigue el modelo de diseño asincrónico de .NET Framework

  1. Divida un método de servicio Web XML sincrónico en dos métodos con el mismo nombre base, el nombre de uno de los métodos comenzando con Begin y el otro con End.

  2. La lista de parámetros del método Begin contiene todos los parámetros in y by reference para la funcionalidad del método más dos anexados al final.

    • Los parámetros By reference se incluyen como parámetros in.
    • El segundo parámetro empezando por el último debe ser un AsyncCallback. El parámetro AsyncCallback permite que un cliente proporcione un delegado, al que se llama una vez finalizado el método. Cuando un método de servicio Web XML asincrónico llama a otro método asincrónico, se puede pasar este parámetro al segundo método a partir del último parámetro para dicho método.
    • El último parámetro es un Object. El parámetro Object permite que un llamador proporcione al método la información de estado. Cuando un método de servicio Web XML asincrónico llama a otro método asincrónico, se puede pasar este parámetro al último parámetro de ese método.
    • El valor devuelto debe ser de tipo IAsyncResult.

    El siguiente ejemplo de código contiene un método Begin, que tiene un parámetro String específico de la funcionalidad del método.

    [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 lista de parámetros del método End consta de un tipo IAsyncResult seguido de los parámetros out y by reference específicos de la funcionalidad del método.

    • El valor devuelto es del mismo tipo que el valor que devuelve un método de servicio Web XML sincrónico.
    • Los parámetros By reference se incluyen como parámetros out.

    El siguiente ejemplo de código contiene un método End, que devuelve un tipo AuthorRoyalties definido por el usuario.

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

    El siguiente ejemplo de código contiene un método de servicio Web XML asincrónico que se comunica de forma asincrónica con otro método de servicio 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
    

En el siguiente ejemplo de código se muestra cómo encadenar llamadas asincrónicas cuando un método de servicio Web XML efectúa más de una llamada asincrónica y las llamadas se deben ejecutar secuencialmente. El método BeginGetAuthorRoyalties llama asincrónicamente para determinar si el autor que se pasa es válido y configura una devolución de llamada intermedia denominada AuthorRoyaltiesCallback para recibir los resultados. A continuación la función de devolución de llamada intermedia llama de forma asincrónica para obtener los derechos de autor, siempre que el autor sea válido.

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

Vea también

Comunicar con servicios Web XML de forma asincrónica | Incluir llamadas asincrónicas | Generar servicios Web XML mediante ASP.NET