Compartir vía


Procedimiento para llamar a operaciones de manera asincrónica mediante un generador de canales

En este tema se cubre cómo un cliente puede obtener acceso de forma asincrónica a una operación del servicio al utilizar una aplicación de cliente basada en ChannelFactory<TChannel>. (Al utilizar un objeto System.ServiceModel.ClientBase<TChannel> para invocar un servicio, puede utilizar el modelo de llamada asincrónica orientado a eventos. Para obtener más información, consulte Cómo llamar a operaciones de servicio WCF de forma asincrónica. Para obtener más información sobre el modelo de llamada asincrónica basado en eventos, consulte Patrón asincrónico basado en eventos (EAP)).

El servicio en este tema implementa la interfaz ICalculator. El cliente puede llamar a las operaciones en esta interfaz de forma asincrónica, lo que significa que las operaciones como Add se dividen en dos métodos, BeginAdd y EndAdd, de los cuales el primero inicia la llamada y el segundo recupera el resultado cuando la operación termina. Para obtener un ejemplo que muestre cómo implementar una operación de manera asincrónica en un servicio, consulte Procedimiento para implementar una operación de servicio asincrónica. Para obtener más información sobre las operaciones sincrónicas y asincrónicas, consulte Operaciones sincrónicas y asincrónicas.

Procedimiento

Para llamar a operaciones de servicio WCF de forma asincrónica

  1. Ejecute la utilidad de metadatos de ServiceModel (Svcutil.exe) con la opción /async como se muestra en el siguiente comando.

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

    Esto genera una versión de cliente asincrónica del contrato de servicio para la operación.

  2. Cree una función de devolución de llamada a la que se va a llamar cuando la operación asincrónica haya finalizado, tal y como aparece en el siguiente código de ejemplo.

    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. Para obtener acceso de forma asincrónica a una operación de servicio, cree el cliente y llame a Begin[Operation] (por ejemplo, BeginAdd) y especifique una función de devolución de llamada, tal y como se muestra en el siguiente código de ejemplo.

    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)
    

    Cuando la función de devolución de llamada se ejecuta, el cliente llama a End<operation>EndAdd (por ejemplo, ) para recuperar el resultado.

Ejemplo

El servicio que se usa con el código de cliente que se utiliza en el procedimiento anterior implementa la interfaz ICalculator tal y como se muestra en el código siguiente. En el lado del servicio, el entorno de ejecución de Windows Communication Foundation (WCF) invoca de manera sincrónica a las operaciones Add y Subtract del contrato, aunque los pasos precedentes del cliente se invoquen de manera asincrónica en el cliente. Las operaciones Multiply y Divide se utilizan para invocar de forma asincrónica el servicio en el lado del servicio, incluso aunque el cliente los invoque de forma sincrónica. Este ejemplo establece la propiedad AsyncPattern en true. Este valor de la propiedad, en combinación con la implementación del modelo asincrónico de .NET Framework, indica al entorno de ejecución que invoque la operación de forma asincrónica.

[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