Partager via


Comment : appeler des opérations de service WCF de façon asynchrone

Cette rubrique présente comment un client peut accéder de façon asynchrone à une opération de service. Le service dans cette rubrique implémente l'interface ICalculator. Le client peut appeler les opérations sur cette interface de manière asynchrone à l'aide du modèle d'appel asynchrone commandé par événement. (Pour plus d'informations sur le modèle d'appel asynchrone basé sur les événements, consultez Multithreaded Programming with the Event-based Asynchronous Pattern). Pour obtenir un exemple illustrant comment implémenter une opération de façon asynchrone dans un service, consultez Comment : implémenter une opération de service asynchrone. Pour plus d'informations sur les opérations synchrones et asynchrones, consultez Opérations synchrones et asynchrones.

ms730059.note(fr-fr,VS.100).gifRemarque :
Le modèle d'appel asynchrone commandé par événement n'est pas pris en charge lorsqu'il utilise un ChannelFactory. Pour plus d'informations sur les appels asynchrones à l'aide de ChannelFactory, consultez Comment : appeler des opérations de façon asynchrone à l'aide d'une fabrication de canal.

Procédure

Pour appeler des opérations de service WCF de façon asynchrone

  1. Exécutez l'outil Outil Service Model Metadata Tool (Svcutil.exe) en définissant les deux options /async et /tcv:Version35 comme illustré dans la commande suivante.

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

    Cette opération génère en plus des opérations asynchrones basées sur les délégués standard et des opérations synchrones, un client WCF qui contient :

    • Deux opérations <operationName>Async destinées à l'approche de l'appel asynchrone basé sur les événements. Par exemple :

      Public Overloads Sub AddAsync(ByVal n1 As Double, ByVal n2 As Double)
          Me.AddAsync(n1, n2, Nothing)
      End Sub
      
      Public Overloads Sub AddAsync(ByVal n1 As Double, ByVal n2 As Double, ByVal userState As Object)
          If (Me.onBeginAddDelegate Is Nothing) Then
              Me.onBeginAddDelegate = AddressOf Me.OnBeginAdd
          End If
          If (Me.onEndAddDelegate Is Nothing) Then
              Me.onEndAddDelegate = AddressOf Me.OnEndAdd
          End If
          If (Me.onAddCompletedDelegate Is Nothing) Then
              Me.onAddCompletedDelegate = AddressOf Me.OnAddCompleted
          End If
          MyBase.InvokeAsync(Me.onBeginAddDelegate, New Object() {n1, n2}, Me.onEndAddDelegate, Me.onAddCompletedDelegate, userState)
      End Sub
      
      public void AddAsync(double n1, double n2)
      {
          this.AddAsync(n1, n2, null);
      }
      
      public void AddAsync(double n1, double n2, object userState)
      {
          if ((this.onBeginAddDelegate == null))
          {
              this.onBeginAddDelegate = new BeginOperationDelegate(this.OnBeginAdd);
          }
          if ((this.onEndAddDelegate == null))
          {
              this.onEndAddDelegate = new EndOperationDelegate(this.OnEndAdd);
          }
          if ((this.onAddCompletedDelegate == null))
          {
              this.onAddCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnAddCompleted);
          }
          base.InvokeAsync(this.onBeginAddDelegate, new object[] {
                      n1,
                      n2}, this.onEndAddDelegate, this.onAddCompletedDelegate, userState);
      }
      
    • Les événements terminés d'opérations de la forme <operationName>Completed destinés à l'approche de l'appel asynchrone basé sur les événements. Par exemple :

      Public Event AddCompleted As System.EventHandler(Of AddCompletedEventArgs)
      
      public event System.EventHandler<AddCompletedEventArgs> AddCompleted;
      
    • Les types System.EventArgs pour chaque opération (de la forme <operationName>CompletedEventArgs) destinés à l'approche de l'appel asynchrone basé sur les événements. Par exemple :

      <System.Diagnostics.DebuggerStepThroughAttribute(),  _
       System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")>  _
      Partial Public Class AddCompletedEventArgs
          Inherits System.ComponentModel.AsyncCompletedEventArgs
      
          Private results() As Object
      
          Public Sub New(ByVal results() As Object, ByVal exception As System.Exception, ByVal cancelled As Boolean, ByVal userState As Object)
              MyBase.New(exception, cancelled, userState)
              Me.results = results
          End Sub
      
          Public ReadOnly Property Result() As Double
              Get
                  MyBase.RaiseExceptionIfNecessary
                  Return CType(Me.results(0),Double)
              End Get
          End Property
      End Class
      
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
      public partial class AddCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
      {
          private object[] results;
      
          public AddCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : 
                  base(exception, cancelled, userState)
          {       this.results = results;         }
      
          public double Result
          {
              get            {
                  base.RaiseExceptionIfNecessary();
                  return ((double)(this.results[0]));
              }
          }
      }
      
  2. Dans l'application d'appel, créez une méthode de rappel à appeler au terme de l'opération asynchrone en vous conformant à l'exemple de code suivant.

    ' Asynchronous callbacks for displaying results.
    Private Shared Sub AddCallback(ByVal sender As Object, ByVal e As AddCompletedEventArgs)
    
        Console.WriteLine("Add Result: {0}", e.Result)
    
    End Sub
    
    // Asynchronous callbacks for displaying results.
    static void AddCallback(object sender, AddCompletedEventArgs e)
    {
        Console.WriteLine("Add Result: {0}", e.Result);
    }
    
  3. Avant d'appeler l'opération, utilisez un nouveau System.EventHandler générique de type <operationName>EventArgs pour ajouter la méthode de gestionnaire d'événements (créée à l'étape précédente) à l'événement <operationName>Completed. Ensuite, appelez la méthode <operationName>Async. Par exemple :

    ' AddAsync
    Dim value1 As Double = 100
    Dim value2 As Double = 15.99
    AddHandler client.AddCompleted, AddressOf AddCallback
    client.AddAsync(value1, value2)
    Console.WriteLine("Add({0},{1})", value1, value2)
    
    // AddAsync
    double value1 = 100.00D;
    double value2 = 15.99D;
    client.AddCompleted += new EventHandler<AddCompletedEventArgs>(AddCallback);
    client.AddAsync(value1, value2);
    Console.WriteLine("Add({0},{1})", value1, value2);
    

Exemple

ms730059.note(fr-fr,VS.100).gifRemarque :
Les règles de conception pour le modèle asynchrone basé sur les événements stipulent que si plusieurs valeurs sont retournées, une valeur est retournée comme la propriété Result et les autres sont retournées comme les propriétés sur l'objet EventArgs. Il en découle que si un client importe des métadonnées à l'aide des options de commande asynchrone basées sur les événements et que l'opération retourne plusieurs valeurs, l'objet EventArgs par défaut retourne une valeur comme la propriété Result et le reste sont des propriétés de l'objet EventArgs. Pour recevoir l'objet message comme la propriété Result et que les valeurs retournées sur cet objet soient des propriétés, utilisez l'option de commande /messageContract. Cette opération génère une signature qui retourne le message de réponse comme la propriété Result sur l'objet EventArgs. Toutes les valeurs de retour internes sont ensuite des propriétés de l'objet de message de réponse.

Imports System

Namespace Microsoft.ServiceModel.Samples

    ' The service contract is defined in generatedClient.vb, generated from the service by the svcutil tool.

    Class Client

        Public Shared Sub Main()

            Console.WriteLine("Press <ENTER> to terminate client once the output is displayed.")
            Console.WriteLine()

            ' Create a client
            Dim client As New CalculatorClient()

            ' AddAsync
            Dim value1 As Double = 100
            Dim value2 As Double = 15.99
            AddHandler client.AddCompleted, AddressOf AddCallback
            client.AddAsync(value1, value2)
            Console.WriteLine("Add({0},{1})", value1, value2)

            ' SubtractAsync
            value1 = 145
            value2 = 76.54
            AddHandler client.SubtractCompleted, AddressOf SubtractCallback
            client.SubtractAsync(value1, value2)
            Console.WriteLine("Subtract({0},{1})", value1, value2)

            ' Multiply
            value1 = 9
            value2 = 81.25
            Dim result As Double = client.Multiply(value1, value2)
            Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result)

            ' Divide
            value1 = 22
            value2 = 7
            result = client.Divide(value1, value2)
            Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result)
            Console.ReadLine()

            'Closing the client gracefully closes the connection and cleans up resources
            client.Close()

        End Sub
        ' Asynchronous callbacks for displaying results.
        Private Shared Sub AddCallback(ByVal sender As Object, ByVal e As AddCompletedEventArgs)

            Console.WriteLine("Add Result: {0}", e.Result)

        End Sub
        Private Shared Sub SubtractCallback(ByVal sender As Object, ByVal e As SubtractCompletedEventArgs)

            Console.WriteLine("Subtract Result: {0}", e.Result)

        End Sub

    End Class

End Namespace
using System;

namespace Microsoft.ServiceModel.Samples
{
    // The service contract is defined in generatedClient.cs, generated from the service by the svcutil tool.

    class Client
    {
        static void Main()
        {
            Console.WriteLine("Press <ENTER> to terminate client once the output is displayed.");
            Console.WriteLine();

            // Create a client
            CalculatorClient client = new CalculatorClient();

            // AddAsync
            double value1 = 100.00D;
            double value2 = 15.99D;
            client.AddCompleted += new EventHandler<AddCompletedEventArgs>(AddCallback);
            client.AddAsync(value1, value2);
            Console.WriteLine("Add({0},{1})", value1, value2);

            // SubtractAsync
            value1 = 145.00D;
            value2 = 76.54D;
            client.SubtractCompleted += new EventHandler<SubtractCompletedEventArgs>(SubtractCallback);
            client.SubtractAsync(value1, value2);
            Console.WriteLine("Subtract({0},{1})", value1, value2);

            // Multiply
            value1 = 9.00D;
            value2 = 81.25D;
            double result = client.Multiply(value1, value2);
            Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);

            // Divide
            value1 = 22.00D;
            value2 = 7.00D;
            result = client.Divide(value1, value2);
            Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);

            Console.ReadLine();

            //Closing the client gracefully closes the connection and cleans up resources
            client.Close();
        }

        // Asynchronous callbacks for displaying results.
        static void AddCallback(object sender, AddCompletedEventArgs e)
        {
            Console.WriteLine("Add Result: {0}", e.Result);
        }

        static void SubtractCallback(object sender, SubtractCompletedEventArgs e)
        {
            Console.WriteLine("Subtract Result: {0}", e.Result);
        }
    }
}

Voir aussi

Tâches

Asynchronous