12.6 Call a Web Method Asynchronously


Problem

You need to invoke a Web method on another thread so that your program can continue with other tasks while waiting for the response.

Solution

Use the proxy class's built-in asynchronous methods, which are provided for every Web method supported by the XML Web service. The methods are named BeginXXX and EndXXX , where XXX is the name of the original, synchronous method.

Discussion

The automatically generated proxy class has the basic features that you need to call any Web method asynchronously. For example, consider the Wait Web method shown in the following code, which pauses for a random number of seconds (10 to 19).

 using System; using System.Web.Services; public class Wait : System.Web.Services.WebService {     [WebMethod]     public int Wait() {         DateTime start = DateTime.Now;         Random rand = new Random();         TimeSpan delay = new TimeSpan(0, 0, rand.Next(10, 20));         while (DateTime.Now < start.Add(delay)) {}         return delay.Seconds;     } } 

The automatically generated proxy class will include three methods: Wait , BeginWait , and EndWait . Wait calls the Web method synchronously. BeginWait starts the method on a separate thread and returns immediately. The BeginXXX method always takes two parameters more than the original method and returns an IAsyncState object. The last two parameters are used to submit state information and a callback. The IAsyncState object allows you to determine when the call has completed. For example, you can periodically check the IAsyncState.IsComplete property to determine if the method call has finished. When it's finished, you submit the IAsyncState object to the EndWait method, which completes the call and returns the expected Web method return value. If you call EndWait before the method is completed, your code will then wait for it to complete.

There are two common asynchronous patterns with XML Web services. One is calling several asynchronous Web methods at once, and then waiting for them to complete. This approach allows you to collapse the total waiting time, and it works best with a System.Threading.WaitHandle object. Here's an example that calls the same Wait method three times:

 using System; using System.Threading; public class WaitClient {     [MTAThread]     private static void Main() {         localhost.WaitService proxy = new localhost.WaitService();         // Keep track of the elapsed time.         DateTime startDate = DateTime.Now;         // Call three methods asynchronously.         IAsyncResult handle1 = proxy.BeginWait(null, null);         IAsyncResult handle2 = proxy.BeginWait(null, null);         IAsyncResult handle3 = proxy.BeginWait(null, null);         WaitHandle[] waitHandle = {handle1.AsyncWaitHandle,           handle2.AsyncWaitHandle, handle3.AsyncWaitHandle};         // Wait for all the calls to finish.         WaitHandle.WaitAll(waitHandle);         int totalDelay = proxy.EndWait(handle1) + proxy.EndWait(handle2) +           proxy.EndWait(handle3);         TimeSpan elapsedTime = DateTime.Now - startDate;         Console.WriteLine("Completed after " + elapsedTime.ToString());         Console.WriteLine("Total delay time: " + totalDelay.ToString());     } } 

In this case, you'll see that the elapsed time is less than the total delay time:

 Completed after 00:00:20.2591312 Total delay time: 47 

Another common technique with asynchronous Web methods is to use a callback. With callbacks, you submit a delegate that identifies a specific method in your code. When the Web method is complete, this delegate is invoked and passed the appropriate IAsyncResult object.

Here's a code snippet that calls the BeginWait method with a callback:

 AsyncCallback callback = new AsyncCallback(Callback); // Start the method asynchronously, with the callback.  proxy.BeginWait(callback, proxy); 

And here's the callback that will be triggered when the operation is complete:

 public static void Callback(IAsyncResult handle) {     localhost.WaitService proxy = (localhost.WaitService)handle.AsyncState;     int result = proxy.EndWait(handle);     Console.WriteLine("Waited " + result.ToString()); } 



C# Programmer[ap]s Cookbook
C# Programmer[ap]s Cookbook
ISBN: 735619301
EAN: N/A
Year: 2006
Pages: 266

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net