Cómo: Implementar una operación de servicio asincrónica

En las aplicaciones de Windows Communication Foundation (WCF), una operación de servicio se puede implementar de forma asincrónica o sincrónica sin dictar al cliente cómo llamarla. Por ejemplo, las operaciones de servicio asincrónicas se pueden llamar de forma sincrónica y las operaciones de servicio sincrónicas se pueden llamar de forma asincrónica. Para obtener un ejemplo que muestra cómo llamar a una operación de forma asincrónica en una aplicación cliente, consulte Cómo: Llamar a Operaciones de Servicio de Forma Asincrónica. Para obtener más información sobre las operaciones sincrónicas y asincrónicas, consulte Diseño de contratos de servicio y operaciones sincrónicas y asincrónicas. En este tema se describe la estructura básica de una operación de servicio asincrónica, el código no está completo. Para obtener un ejemplo completo de los lados del servicio y del cliente, consulte Asincrónico.

Implementación de una operación de servicio de forma asincrónica

  1. En el contrato de servicio, declare un par de métodos asincrónicos según las directrices de diseño asincrónico de .NET. El Begin método toma un parámetro, un objeto de devolución de llamada y un objeto de estado, y devuelve un System.IAsyncResult junto con un método End correspondiente que toma un System.IAsyncResult y devuelve el valor de retorno. Para obtener más información sobre las llamadas asincrónicas, vea Modelos de diseño de programación asincrónica.

  2. Marque el Begin método del par de métodos asincrónicos con el System.ServiceModel.OperationContractAttribute atributo y establezca la propiedad OperationContractAttribute.AsyncPattern a true. Por ejemplo, el código siguiente realiza los pasos 1 y 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. Implemente el par de métodos Begin/End en su clase de servicio según las pautas de diseño asincrónico. Por ejemplo, el siguiente ejemplo de código muestra una implementación en la que se escribe una cadena en la consola en las partes Begin y End de la operación de servicio asincrónica, y se devuelve el valor de retorno de la operación End al cliente. Para obtener el ejemplo de código completo, consulte la sección Ejemplo.

    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
    

Ejemplo

Los ejemplos de código siguientes muestran:

  1. Una interfaz de contrato de servicio con:

    1. Una operación sincrónica SampleMethod .

    2. Una operación asincrónica BeginSampleMethod .

    3. Un par de operaciones asincrónicas BeginServiceAsyncMethod/EndServiceAsyncMethod .

  2. Implementación de servicio mediante un System.IAsyncResult objeto .

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

Consulte también