If you simply call a Web service method from a client program (via a Web service proxy), the call is synchronous. That is, your client application will not process any other commands until the SOAP response comes back from the server. The proxy classes generated by Visual Studio .NET (or by wsdl.exe) also enable you to make asynchronous calls to a Web service. When you make an asynchronous call, the client sends the SOAP request, but it is not blocked while waiting for the SOAP response. The Web service server does not require any special configuration to support asynchronous calls. In fact, as far as the server knows, the call is synchronous. All the additional processing is done at the client. The CLR sends the SOAP request and then monitors a system I/O completion port to wait for the SOAP response. You can handle asynchronous calls in two ways using a callback delegate and using a WaitHandle object. Using a Callback Delegate In this method, you provide a delegate that the runtime can invoke when the results are returned. The following code example shows how to modify the Example6_2 project to invoke a Web method asynchronously using a callback delegate: private void btnGetBug_Click(object sender, System.EventArgs e) { // Connect to the Web service localhost.BugService bugService = new localhost.BugService(); // Create a delegate to handle the callback AsyncCallback cb = new AsyncCallback(WebServiceCallback); // Launch the asynchronous call bugService.BeginGetBug(1, cb, bugService); // Do some work while waiting for it to return for (int intI=1; intI <= 100; intI++) txtDescription.AppendText(intI.ToString() + Environment.NewLine); } // Callback to handle the asynchronous return private void WebServiceCallback(IAsyncResult ar) { // Get the returned Web service instance localhost.BugService bugService = (localhost.BugService) ar.AsyncState; // Finish the work localhost.Bug bug = bugService.EndGetBug(ar); // And display the result txtDescription.AppendText(bug.Description + Environment.NewLine); } The callback method for an asynchronous Web method call must take a single argument of type IAsyncResult. For each Web method, the proxy class will contain corresponding Begin and End methods. The Begin method takes all the arguments of the original method, plus a reference to the Web service object itself (necessary because you can have multiple asynchronous calls outstanding at any given time), and the address of the callback method (contained in an AsyncCallback object). When the results of the call are available, the callback method is invoked. Within the callback method, you can retrieve the original Web service object and then call its End method to get the result of the method call. Using the WaitHandle Object The WaitHandle object essentially lets you turn the asynchronous process back into a synchronous process, as shown here: private void btnGetBug_Click(object sender, System.EventArgs e) { // Connect to the Web service localhost.BugService bugService = new localhost.BugService(); // Holds the status of the asynchronous call IAsyncResult ar; // Launch the asynchronous call ar = bugService.BeginGetBug(1, null, null); // Do some work while waiting for it to return for (int intI=1; intI <= 90; intI++) txtDescription.AppendText(intI.ToString() + Environment.NewLine); // Now wait for the method to come back WaitHandle wh = ar.AsyncWaitHandle; wh.WaitOne(); localhost.Bug bug = bugService.EndGetBug(ar); // And display the result txtDescription.AppendText(bug.Description + Environment.NewLine); // Do some final work for (int intI=91; intI <= 100; intI++) txtDescription.AppendText(intI.ToString() + Environment.NewLine); } This code example doesn't use a callback method. Instead, it uses the BeginGetBug() method to start the asynchronous method call, and it saves the result from this call as an IAsyncResult object. When I was ready to wait for the results of the call, I retrieved a WaitHandle object from this object's AsyncWaitHandle property. The WaitOne() method of this object causes the thread to pause until the results are ready. | If you have multiple outstanding asynchronous Web method calls, you can wait for them all to come back by using the static WaitHandle.WaitAll() method, or you can wait for the first one to return by using the static WaitHandle.WaitAny() method. |
You can manage asynchronous Web method calls in two other ways: You can use a loop to poll the value of the IAsyncResult.IsCompleted property. This property returns false while the method is still doing work, and true when the End method is ready to call. You can simply call the End method in your code when you're ready to wait synchronously for the result. This is equivalent to using the WaitHandle.WaitOne() method that you saw in the previous code example. |