Calling Multiple Web Services Asynchronously
Posted by Keith Elder | Posted in .Net, Asp.Net, Programming, Smart Clients | Posted on 16-03-2006
There are two ways to call web services: synchronously and asynchronously. Below is an example of a syncronous web call. The HelloWorld() call will not get executed until the ReturnLastCustomer() is completed. In some cases this is fine. For example if you need the information from ReturnLastCustomer() to then call the HelloWorld() example.
Syncronous Web Service Call
localhost.Service proxy = new WindowsApplication3.localhost.Service();
localhost.MyCustomObject myObject = proxy.ReturnCustomObject();
// Make another call to web service
string hello = proxy.HelloWorld();
In the example above we wouldn’t really care if one method completed before another. There may be code below it that can go ahead and get started processing. To do this we change this to call the service asynchronously. The idea behind the asynchronous call is we setup an event that gets notified through a delegate that the web service method is done with processing. Here is how the synchronous example above would look called asynchronously. It may look like a little more code, but in Visual Studio as you type this just press tab when it gives you a tooltip help and it will generate the right side of the += as well as the method stub for the call back.
Asyncronous Web Service Call
public Form1()
{
InitializeComponent();
localhost.Service proxy = new WindowsApplication3.localhost.Service();
proxy.ReturnLastCustomerCompleted += new WindowsApplication3.localhost.ReturnLastCustomerCompletedEventHandler(proxy_ReturnLastCustomerCompleted);
proxy.ReturnLastCustomerAsync();
// Make another call to web service
proxy.HelloWorldCompleted += new WindowsApplication3.localhost.HelloWorldCompletedEventHandler(proxy_HelloWorldCompleted);
proxy.HelloWorldAsync();
}
void proxy_HelloWorldCompleted(object sender, WindowsApplication3.localhost.HelloWorldCompletedEventArgs e)
{
string hello = e.Result;
}
void proxy_ReturnLastCustomerCompleted(object sender, WindowsApplication3.localhost.ReturnLastCustomerCompletedEventArgs e)
{
localhost.MyCustomObject myObject = e.Result;
}
The Problem
The problem with the above example is depending on the speed of how things get processed we will get random errors that an asynchronous call is currently being processed. The good news is there is an easy way to address this in .Net 2.0. There are two overrides for the Async calls. The first one is it takes the parameters of your web service call. The second override adds another parameter of type “object userState”. This allows us to pass in a unique identifier of the call.
To make sure our asynchronous example above works we need to make sure these calls can run at the same time. It is a simple change and that would look like this:
Calling Two Asynchronous Calls At the Same Time
localhost.Service proxy = new WindowsApplication3.localhost.Service();
proxy.ReturnLastCustomerCompleted += new WindowsApplication3.localhost.ReturnLastCustomerCompletedEventHandler(proxy_ReturnLastCustomerCompleted);
proxy.ReturnLastCustomerAsync(Guid.NewGuid());
// Make another call to web service
proxy.HelloWorldCompleted += new WindowsApplication3.localhost.HelloWorldCompletedEventHandler(proxy_HelloWorldCompleted);
proxy.HelloWorldAsync(Guid.NewGuid());
Notice the only difference in how we call the methods is we generate a new Guid as our userState object. This allows the calls to keep track of the state of each call. Pretty easy problem to get around but if you don’t explore your overrides of method calls, you may have missed this one. Being able to call multiple web service methods asynchronously at the same time is pretty important when writing a Smart Client so you’ll probably use this more in this scenario. With larger Smart Clients you typically have things running in the background to check on statuses, update queues, as well as carry calls to save and return data. This is how you get around that.
Thanks for useful article.
But what can we do in CF.NET (3.5).
Thanks for the tip 🙂
I was getting errors when trying to call a method many times async
Thank you very much for the fantastic article.
Really really very useful.
Thanks for the hint 🙂