3 out of 8 rated this helpful - Rate this topic

How to: Call WCF Service Operations Asynchronously

This topic covers how a client can access a service operation asynchronously. The service in this topic implements the ICalculator interface. The client can call the operations on this interface asynchronously by using the event-driven asynchronous calling model. (For more information about the event-based asynchronous calling model, see Multithreaded Programming with the Event-based Asynchronous Pattern). For an example that shows how to implement an operation asynchronously in a service, see How to: Implement an Asynchronous Service Operation. For more information about synchronous and asynchronous operations, see Synchronous and Asynchronous Operations.

ms730059.note(en-us,VS.100).gifNote:
The event-driven asynchronous calling model is not supported when using a ChannelFactory. For information about making asynchronous calls using the ChannelFactory, see How to: Call Operations Asynchronously Using a Channel Factory.

Procedure

To call WCF service operations asynchronously

  1. Run the ServiceModel Metadata Utility Tool (Svcutil.exe) tool with both the /async and the /tcv:Version35 command options together as shown in the following command.

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

    This generates, in addition to the synchronous and standard delegate-based asynchronous operations, a WCF client class that contains:

    • Two <operationName>Async operations for use with the event-based asynchronous calling approach. For example:

      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);
      }
      
      
    • Operation completed events of the form <operationName>Completed for use with the event-based asynchronous calling approach. For example:

      public event System.EventHandler<AddCompletedEventArgs> AddCompleted;
      
      
    • System.EventArgs types for each operation (of the form <operationName>CompletedEventArgs) for use with the event-based asynchronous calling approach. For example:

      [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. In the calling application, create a callback method to be called when the asynchronous operation is complete, as shown in the following sample code.

    // Asynchronous callbacks for displaying results.
    static void AddCallback(object sender, AddCompletedEventArgs e)
    {
        Console.WriteLine("Add Result: {0}", e.Result);
    }
    
    
  3. Prior to calling the operation, use a new generic System.EventHandler of type <operationName>EventArgs to add the handler method (created in the preceding step) to the <operationName>Completed event. Then call the <operationName>Async method. For example:

    // 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);
    
    

Example

ms730059.note(en-us,VS.100).gifNote:
The design guidelines for the event-based asynchronous model state that if more than one value is returned, one value is returned as the Result property and the others are returned as properties on the EventArgs object. One result of this is that if a client imports metadata using the event-based asynchronous command options and the operation returns more than one value, the default EventArgs object returns one value as the Result property and the remainder are properties of the EventArgs object.If you want to receive the message object as the Result property and have the returned values as properties on that object, use the /messageContract command option. This generates a signature that returns the response message as the Result property on the EventArgs object. All internal return values are then properties of the response message object.

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);
        }
    }
}

See Also

Did you find this helpful?
(1500 characters remaining)
Community Content Add
Annotations FAQ
Exception handling?
Where is the exception handling? I want to know what happens if the service is offline or there is no local connection to the network.
Incomplete Sample
This article is incomplete, and appears to have been rushed to print. It needs to be heavily revised.
Generate asynchronous operations
Thanks for your feedback, please keep it coming. I can assure you that we at Microsoft do care.

By default, only synchronous (blocking) methods are generated for use by the WCF client, for example:
- DoWork()

Right-clicking on the proxy file and checking “Generate asynchronous operations” will additionally generate code (event + method) for easy async. programming, just like it is done by default in Silverlight when using WCF RIA services:
- DoWorkComplete
- DoWorkAsync()
Awful samples !
The quality of these samples is downright shoddy !
Doesn't anyone care at Microsoft !!
Client closing connection in wrong place
The client code is closing the client connection in the same processing as the asynch calls - in a more real world example the last async call would probably fail because the connection was closed before it executed. The intervening synch calls & ReadLine() stop this happening in this example.
A better approach is to close the client connection as part of the method handling the completed event, the sender object can be cast to the appropriate type and close() called on it.
This is a terrible example.
This is a terrible example. Keep it simple.
This is sample is confusing
I agree with toadware. I really dislike this sample and it is really confusing.

In order to understand better async operation with WCF, I had to visit dotnetcurry http://www.dotnetcurry.com/ShowArticle.aspx?ID=237

If you want to offer easy to understand samples, see how jquery documentation is done. I really like how jquery documentation is done (http://api.jquery.com/fadeOut/) and I don't understand why msdn team shows so bad examples. This layout has changed again and we just can't find what we want.