- Introduction
- Implementing a Basic Web Service in C#
- Exploring the Web Service Proxy Class
- Invoking a Web Service Asynchronously
- Summary
Invoking a Web Service Asynchronously
We assume that the amount of airport information will take a few seconds to compile, which is plenty of time to do some other work. Hence, we can use the signature of the proxy methods as a starting point to figure out how to call the Web Service asynchronously.
Invoking the Web Service
The signature of BeginGetAirports in Listing 3 indicates that you need to pass a string representing the state search string, followed by an AsyncCallback delegate and an object that can represent any information you want to send to the Begin method. You'll get back an object that implements System.IAsyncResult immediately from the Begin method. This object is used to synchronize the callback method with a specific asynchronous call. Listing 4 assumes that a web reference has been made to our Web Service and shows the code for the asynchronous call.
Listing 4Invoking a Web Service Asynchronously
localhost.Service1 service = new localhost.Service1(); private void button1_Click(object sender, System.EventArgs e) { IAsyncResult result = service.BeginGetAirports( textBox1.Text, new AsyncCallback(Callback), null ); } delegate void MyDelegate(IList list, Type type); private void Callback(IAsyncResult result) { localhost.Airport[] airports = service.EndGetAirports(result); if( InvokeRequired ) Invoke(new MyDelegate(CreateUserInterface), new Object[]{ airports, typeof(Airport)}); }
The first statement creates an instance of the Web Service class, named Service1. The button1_Click method performs the asynchronous call, catching the return result, passing the state argument from a text box, creating an instant of the callback, and null for the third argument.
The argument new AsynchCallback(Callback) shows you how to construct an instance of a delegate objecta callback. If you check the help, you'll see that the signature of the method named Callback matches that of an AsyncCallback delegate.
Waiting for the Return Value
The delegate method Callback will be called when the Web Service needs to talk to our application. Assuming that everything works correctly in the Web Service, the data should be ready when Callback is called by the Web Service.
TIP
The CodeDOM in .NET is used by WSDL.exe to generate the proxy class. The CodeDOM is a great place to explore if you're interested in writing code generators.
The statement in Listing 4 that contains EndGetAirports passes the IAsyncResult the Web Service sent to us, and we send that back to the Web Service to ensure that we're talking to the correct thread in the service. EndGetAirports returns our array of proxy Airport objects defined in the Reference.cs generated file.
The final code beginning with if( InvokeRequired ) is used to manage interaction with the Windows Forms application representing the client. The Web Service Callback is not on the same thread that the form is on, so we can't interact with the Windows Forms controls directly. To display the list of airports on the form, I used another delegate to invoke CreateUserInterface, which dynamically generates form controls based on the type of the object passed. (Due to space constraints this code isn't shown here, but can be found in my C# book and on my web site at www.softconcepts.com.)
TIP
To view the threads working in the sample application, place a breakpoint on the callback method in the client and select Debug, Windows, Threads.
There are several options that you can use while waiting for data to return from an asynchronous call. You can call the EndInvoke proxy, which will block until the data is ready, or you can use a WaitHandle object that you can obtain from the IAsyncResult object returned by the BeginInvoke proxy. The WaitHandle class provides you with three ways to block.
And, of course, the benefit is that you can perform useful work while you're waiting on the asynchronous Web Service call to return. Remember, the BeginInvoke proxy returns immediately, so you can add work in the form of code right after the BeginInvoke proxy is called.