by Dominic Zukiewicz
7. February 2008 14:14
This article is part 1 of
2 articles.
Wouldn't it be great if you could call a web service hundreds, if not thousands of times, and then just wait until the results come back, rather than doing it one at a time?
The System.Threading namespace created WaitHandle.WaitAll(), but this is only useful for threads - how do you call lots of web services asynchronously, and then continue once they have all returned?
Well, one could argue why don't you just call them synchronously? Good idea, but it just means that those extra seconds of time taken waiting, could be put to use by another web service call.
The way to do it is to use an inline delegate. Usually with Event Handlers, you use them to reference a method you would like executed, but with a little ingenuity, you can make it work all in one method.
The example below demonstrates the usefulness of this:
public List GetProducts( int[] productCodes )
{
List products = new List(int, ProductWebService.Product>();
ProductWebService.Products service = new ProductWebService.Products();
//Add a delegate which stores the products and outputs the status.
service.GetProductDataCompleted += delegate(object sender, ProductWebService.GetSupplierProductCodesCompletedEventArgs e)
{
data.Add( (int)e.UserState, e.Result );
Console.Write("Downloaded {0} of {1}\r",products.Count,productCodes.Length);
}
//Send the data asynchronously
foreach(int productCode in productCodes)
{
service.GetProductDataAsync(productCode, productCode);
}
//Wait until all products have been returned, without hogging the resources.
while( productCodes.Length != productCodes.Count)
{
Thread.Sleep(200);
}
return products;
}
You will see that the number updates quite irratically, as the calls come back asynchronously. I thought it was quite nifty. It looks like a handful, but it means that you can monitor the responses from the web service without having to have a global variable to monitor it.
Again - I did manage to solve this problem. For the solution, please see part 2 for the actual answer.