Web Services (ASMX 1.1) Performance Guidelines - Asynchronous Web Methods

From Guidance Share

Jump to: navigation, search

- J.D. Meier, Srinath Vasireddy, Ashish Babbar, and Alex Mackman

Use Asynchronous Web Methods for I/O Operations

Consider using asynchronous Web methods if you perform I/O-bound operations such as:

  • Accessing streams
  • File I/O operations
  • Calling another Web service

The .NET Framework provides the necessary infrastructure to handle these operations asynchronously, and you can return an IAsyncResult interface from these types of operations. The .NET Framework exposes asynchronous methods for I/O-bound operations using the asynchronous design pattern. The libraries that use this pattern have BeginXXX and EndXXX methods.

The following code snippet shows the implementation of an asynchronous Web method calling another Web service.

  // The client W/S 
  public class AsynchWSToWS
    WebServ asyncWs = null;
    public AsynchWSToWS(){
      asyncWs = new WebServ();
    public IAsyncResult BeginSlowProcedure(int milliseconds,AsyncCallback cb, 
                                        object s){
      // make call to other web service and return the IAsyncResult
      return asyncWs.BeginLengthyCall(milliseconds,cb,s);
    [System.Web.Services.WebMethod ]
    public string EndSlowProcedure(IAsyncResult call) {
      return asyncWs.EndLengthyCall(call);
  // The server W/S
  public class WebServ
    public string LengthyCall(int milliseconds){
      return "Hello World";

Asynchronous implementation helps when you want to free up the worker thread instead of waiting on the results to return from a potentially long-running task. For this reason, you should avoid asynchronous implementation whenever your work is CPU bound because you do not have idle CPU to service more threads. In this case, an asynchronous implementation results in increased utilization and thread switching on an already busy processor. This is likely to hurt performance and overall throughput of the processor.

Note You should not use asynchronous Web methods when accessing a database. ADO.NET does not provide asynchronous implementation for handling database calls. Wrapping the operation in a delegate is not an option either because you still block a worker thread. You should only consider using an asynchronous Web method if you are wrapping an asynchronous operation that hands back an IAsyncResult reference.

More Information

You can call a Web service asynchronously regardless of whether or not the Web service has been implemented synchronously or asynchronously. Similarly, you can implement a synchronous or asynchronous Web service, but allow either style of caller. Client-side and server-side asynchronous processing is generally performed to free up the current worker thread to perform additional work in parallel.

The asynchronous implementation of a Web method frees up the worker thread to handle other parallel tasks that can be performed by the Web method. This ensures optimal utilization of the thread pool, resulting in throughput gains.

For normal synchronous operations, the Web services asmx handler uses reflection on the assembly to find out which methods have the WebMethod attribute associated with them. The handler simply calls the appropriate method based on the value of the SOAP-Action HTTP header.

However, the Web services asmx handler treats asynchronous Web methods differently. It looks for methods that adhere to the following rules:

Methods adhere to the asynchronous design pattern:

  • There are BeginXXX and EndXXX methods for the actual XXX method that you need to expose.
  • The BeginXXX method returns an IAsyncResult interface, takes whatever arguments the Web method needs, and also takes two additional parameters of type AsyncCallback and System.Object, respectively.
  • The EndXXX method takes an IAsyncResult as a parameter and returns the return type of your Web method.
  • Both methods are decorated with the WebMethod attribute.

The Web services asmx handler then exposes the method, as shown in the following code snippet.

  IAsyncResult  BeginMyProc(…)
  //the WSDL will show the method as

The Web services asmx handler processes incoming requests for asynchronous methods as follows:

  • Call the BeginXXX method.
  • Pass the reference to an internal callback function as a parameter to the BeginXXX method, along with the other in parameters. This frees up the worker thread processing the request, allowing it to handle other incoming requests. The asmx handler holds on to the HttpContext of the request until processing of the request is complete and a response has been sent to the client.
  • Once the callback is called, call the EndXXX function to complete the processing of the method call and return the response as a SOAP response.
  • Release the HttpContext for the request.

Do Not Use Asynchronous Web Methods When You Depend on Worker Threads

You should not implement Web methods when your asynchronous implementation depends upon callbacks or delegates because they use worker threads internally. Although the delegate frees the worker thread processing the request, it uses another worker thread from the process thread pool to execute the method. This is a thread that can be used for processing other incoming requests to the Web service. The result is that you consume a worker thread for the delegate-based operation and you increase context switching.

Alternatively, you can use synchronous Web methods and decrease the minFreeThreads setting so that the worker threads can take requests and execute them directly.

In this scenario, you could block the original worker thread by implementing the Web method to run synchronously. An example of the delegate-based implementation is shown in the following code snippet.

  // delegate
  public delegate string LengthyProcedureAsyncStub(int milliseconds);
  //actual method which is exposed as a web service
  public string LengthyCall(int milliseconds) { 
    return "Hello World";
  public IAsyncResult BeginLengthyCall(int milliseconds,AsyncCallback cb, 
  object s) {
    LengthyProcedureAsyncStub stub = new LengthyProcedureAsyncStub(LengthyCall);
   //using delegate for asynchronous implementation   
    return stub.BeginInvoke(milliseconds, cb, null); }
  public string EndLengthyCall(IAsyncResult call) {
    return ms.asyncStub.EndInvoke(call);
Personal tools