Export (0) Print
Expand All

Accessing an XML Web Service Asynchronously in Managed Code

When adding a Web reference, Visual Studio generates a proxy class that is capable of calling an XML Web service both synchronously and asynchronously. By using an asynchronous method, you can continue to use the calling thread while waiting for the XML Web service to respond. This makes it possible for you to efficiently use the existing set of threads in the client application, which can be critical if the client is a Web application. The XML Web service does not require special configuration to support asynchronous calls nor does it know in which mode the client is calling it because the request and response message behavior is the same for synchronous and asynchronous calls. Client-side asynchronous calls simply uses a system I/O completion port to efficiently wait for the server's response.

For each synchronous method, the generated proxy class also contains a corresponding Begin and End method. Therefore, if the name of the XML Web service method is ConvertTemperature, the name of the synchronous method in the proxy class is also ConvertTemperature and the additional proxy methods to support asynchronous calls are BeginConvertTemperature and EndConvertTemperature.

Calling an XML Web service asynchronously is a two-step operation. The first step, calling the Begin method, initiates the XML Web service call. The second step, calling the End method, completes the XML Web service call and returns the XML Web service response.

The Begin method returns a System.Web.Services.Protocols.WebClientAsyncResult object. This object, which implements System.IAsyncResult, serves two purposes. First, it provides status about the pending asynchronous call. For example, the IsCompleted property indicates if the operation has completed. Second, by passing this object to the End method, the proxy can identify which request you would like to complete. This is important because you can make multiple asynchronous calls simultaneously.

There are several ways to determine when the asynchronous XML Web service call has completed:

  • The first is to supply a callback delegate to the Begin method. After the XML Web service returns its response, a thread will call the callback from the thread pool; this is likely to be a different thread than the one that you used to call the Begin method. Typically, you will then call the End method inside that callback. Using the callback is the most efficient way to manage usage of your threads since callback functions do not block threads while waiting for the response.
  • The second is to wait using one of the WaitHandle methods of the IAsyncResult.AsyncWaitHandle object. When using the methods of the WaitHandle class, the client can also specify a timeout after which it will abandon waiting for results from the XML Web services it called.
  • The third is to poll the value of IAsyncResult.IsCompleted. When this property returns true, the XML Web service response is available.
  • The fourth is to simply call the End method directly. This method will not return until the asynchronous operation is complete since it uses the IAsyncResult.AsyncWaitHandle.

The WaitHandle class makes it possible for clients to make asynchronous call and wait for:

  • a single XML Web service (WaitHandle.WaitOne),
  • the first of many XML Web services (WaitHandle.WaitAny), or
  • all of many XML Web services (WaitHandle.WaitAll) to return results.

If you are making multiple asynchronous XML Web service calls simultaneously, then you might want to use the WaitHandle.WaitAll method to block the thread until all calls have completed. If you want to process the results as they arrive, you can use the WaitHandle.WaitAny method. This method will indicate that one of the operations has completed and will identify the completed operation.

When accessing XML Web services asynchronously from a Web application, using the methods of the WaitHandle class is the preferred method. Otherwise, if execution in the Web application completes before the asynchronous process calls the callback function, as described in the previous section, it may never have the opportunity to do so if the original function's completion results in the destruction of the instance of the Web Form.

If you want to abort an asynchronous XML Web service call, cast the IAsyncResult returned from the Begin method to WebClientAsyncResult and call its Abort method.

For more information, see Communicating with XML Web Services Asynchronously.

To call an XML Web service asynchronously using a callback function in managed code

  1. Create the application from which you want to access an XML Web service. This application could even be another XML Web service.
  2. Add a Web reference for the XML Web service with which your application will interact. For instructions, see Adding and Removing Web References.
  3. Implement a callback function. The callback function contains the call to the End method of the XML Web service method.
  4. Create an instance of the proxy object in your client code where you want to access the XML Web service.
  5. Call the Begin method of the XML Web service method.
  6. Continue doing any other processing in the client application.
  7. After the XML Web service finishes processing and returns the results to the proxy, the proxy will call the callback function.

    The code shown below is from a Windows application that is accessing an XML Web service for which it has a Web reference (Translator) that contains a proxy class (Service1), which has a Begin method (BeginLongProcess) for calling the XML Web service asynchronously and an End method (EndLongProcess) for completing the call and obtaining the results. In this example, the XML Web service accepts a string, performs some time-consuming translation, and then returns the result. After initiating the asynchronous call to the XML Web service method, the event handler button1_Click returns control to the client. When the XML Web service returns its results, it calls the callback function.

    ' Visual Basic
    Private Sub Button1_Click(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) _
                              Handles Button1.Click
    
       Dim cService As New Translator.Service1()
    
       ' cb is essentially a function pointer to ServiceCallback.
       Dim cb As New AsyncCallback(AddressOf ServiceCallback)
    
       ' Call the Begin method of the proxy class to initiate the
       ' asynchronous call to the XML Web service method. 
       cService.BeginLongProcess(TextBox1.Text, cb, cService)
    
    End Sub
    
    Public Sub ServiceCallback(ByVal ar As IAsyncResult)
    
       Dim cService As Translator.Service1
    
       ' Retrieve the original state for the proxy.
       cService = ar.AsyncState
    
       ' Retrieve results by calling the End method of the proxy class.
       TextBox2.Text = cService.EndLongProcess(ar)
    
    End Sub
    
    // C#
    private void button1_Click(object sender, System.EventArgs e)
    {
       Translator.Service1 cService = new Translator.Service1();
    
       // cb is essentially a function pointer to ServiceCallback.
       AsyncCallback cb = new AsyncCallback(ServiceCallback);
    
       // Call the Begin method of the proxy class to initiate the
       // asynchronous call to the XML Web service method. 
       cService.BeginLongProcess(textBox1.Text, cb, cService);
    }
    
    public void ServiceCallback(IAsyncResult ar)
    {
       // Retrieve the original state for the proxy.
       Translator.Service1 cService = (Translator.Service1)ar.AsyncState;
    
       // Retrieve results by calling the End method of the proxy class
       textBox2.Text = cService.EndLongProcess(ar);
    }
    

To call an XML Web service asynchronously using a WaitHandle in managed code

  1. Create the application from which you want to access an XML Web service. This application could even be another XML Web service.
  2. Add a Web reference for the XML Web service with which your application will interact. When you add a Web reference, Visual Studio creates a proxy class that contains methods for accessing each exposed method of that XML Web service. For instructions, see Adding and Removing Web References.

    To access the XML Web service, you must create an instance of this proxy class and then interact with the methods just as you would with the methods of any other instance of a class.

  3. Include the namespace System.Threading. You will need this namespace to access the WaitHandle class.
  4. Create an instance of the proxy object in your client code where you want to access the XML Web service.
  5. Create an interface to an AsyncResult by calling the Begin method of the XML Web service method, which returns a type that implements IAsyncResult interface.
  6. Continue doing any other processing in the client application.
  7. When you reach a point that you require the results from the XML Web service, use a WaitHandle to halt processing and wait for the results.
  8. Once the XML Web service finishes processing and returns the results to the proxy, the proxy will call the callback function.

    The code shown below is from a Web application that is accessing an XML Web service for which it has a Web reference (Translator) that contains a proxy class (Service1), which has a Begin method (BeginLongProcess) for calling the XML Web service asynchronously and an End method (EndLongProcess) for completing the call and obtaining the results. In this example, the XML Web service accepts a string, performs some time-consuming translation, and then returns the result. After initiating the asynchronous call to the XML Web service method, the client application continues with some additional processing and then waits for the XML Web service to return. When the XML Web service returns, processing continues.

    ' Visual Basic
    Private Sub Button1_Click(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) _
                              Handles Button1.Click
    
       Dim cService As New Translator.Service1()
       Dim ar1 As IAsyncResult
       Dim ar2 As IAsyncResult
    
       ' Call the Begin method of the proxy class to initiate the
       ' asynchronous call to the XML Web service method. 
       ar1 = cService.BeginLongProcess(TextBox1.Text, Nothing, Nothing)
       ar2 = cService.BeginLongProcess(TextBox3.Text, Nothing, Nothing)
    
       '...
       ' Keep processing.
       '...
    
       Dim wh() As WaitHandle = {ar1.AsyncWaitHandle, ar2.AsyncWaitHandle}
    
       ' Waits for both async XML Web service calls to finish.
       WaitHandle.WaitAll(wh)
    
       ' Retrieves the results by calling the End method of the proxy
       ' class.
       TextBox2.Text = cService.EndLongProcess(ar1)
       TextBox4.Text = cService.EndLongProcess(ar2)
    End Sub
    
    // C#
    private void Button1_Click(object sender, System.EventArgs e)
    {
       Translator.Service1 cService = new Translator.Service1();
       IAsyncResult ar1 = cService.BeginLongProcess(TextBox1.Text,
                                                    null, null);
       IAsyncResult ar2 = cService.BeginLongProcess(TextBox3.Text,
                                                    null, null);
    
       //...   
       // Keep processing.
       //...
    
       WaitHandle[] wh = {ar1.AsyncWaitHandle, ar2.AsyncWaitHandle};
       
       // Waits for both async XML Web service calls to finish.
       WaitHandle.WaitAll(wh);
    
       // Retrieves the results by calling the End method of the proxy
       // class.
       TextBox2.Text = cService.EndLongProcess(ar1);
       TextBox4.Text = cService.EndLongProcess(ar2);
    }
    

See Also

Accessing XML Web Services in Managed Code | Communicating with XML Web Services Asynchronously | WaitHandle Class | IAsyncResult Interface | Including Asynchronous Calls

Show:
© 2014 Microsoft