Guide pratique pour implémenter une opération de service asynchrone

Dans les applications Windows Communication Foundation (WCF), une opération de service peut être implémentée de manière asynchrone ou synchrone sans dicter au client comment l’appeler. Par exemple, les opérations de service asynchrones peuvent être appelées de façon synchrone et les opérations de service synchrones peuvent être appelées de façon asynchrone. Pour obtenir un exemple montrant comment appeler une opération de manière asynchrone dans une application cliente, consultez Comment : appeler des opérations de service de manière asynchrone. Pour plus d’informations sur les opérations synchrones et asynchrones, consultez Conception de contrats de service et opérations synchrones et asynchrones. Cette rubrique décrit la structure de base d’une opération de service asynchrone, le code n’est pas complet. Pour obtenir un exemple complet des côtés du service et du client, consultez Asynchrone.

Implémenter une opération de service de façon asynchrone

  1. Dans votre contrat de service, déclarez une paire de méthodes asynchrones en fonction des instructions de conception asynchrone .NET. La méthode Begin prend un paramètre, un objet de rappel et un objet d'état, puis retourne une méthode System.IAsyncResult et une méthode correspondante End qui prennent un System.IAsyncResult et retournent la valeur de retour. Pour plus d’informations sur les appels asynchrones, consultez Modèles de conception de programmation asynchrone.

  2. Marquez la méthode Begin de la paire de méthodes asynchrones avec l'attribut System.ServiceModel.OperationContractAttribute et définissez la propriété OperationContractAttribute.AsyncPattern sur true. Par exemple, le code suivant effectue les étapes 1 et 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. Implémentez la Begin/End paire de méthodes dans votre classe de service en fonction des instructions de conception asynchrones. Par exemple, l'exemple de code suivant montre une implémentation où une chaîne est écrite dans la console à la fois dans les sections Begin et End de l'opération de service asynchrone, et la valeur de retour de l'opération End est renvoyée au client. Pour obtenir l’exemple de code complet, consultez la section Exemple.

    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
    

Exemple

Les exemples de code suivants montrent :

  1. Interface de contrat de service avec :

    1. Opération synchrone SampleMethod .

    2. Opération asynchrone BeginSampleMethod .

    3. Paire d’opérations asynchrone BeginServiceAsyncMethod/EndServiceAsyncMethod .

  2. Implémentation de service à l’aide d’un System.IAsyncResult objet.

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

Voir également