In an
earlier post, I looked at the new async page feature in ASP.NET 2.0. Several people asked the very good question - what if I wanted to make multiple asynchronous Web service calls instead of just one (which is what my sample showed)? Fortunately, they thought of this scenario too, and in addition to asynchronous pages ASP.NET 2.0 they give us asynchronous tasks as well (thanks to
David Taylor for initially pointing me to this new feature and to Erik Olson on the ASP.NET team for discussing some of the details of implementation).
To support multiple, concurrent calls to an asynchronous method, the new Page class provides a RegisterAsyncTask() method that takes an instance of a class called PageAsyncTask. This class consists of three delegates (a start delegate, an end delegate, and a timeout delegate) along with some other state. To use the async task feature, you call RegisterAsyncTask() (typically from your Load event handler) and ASP.NET will take care to issue each task that you register in parallel and take care of synchronizing the results for you. There is also a new top-level Page attribute, asyncTimeout, that defines the maximum number of seconds you will wait for any of the asynchronous tasks to complete before timing out. Note that this feature is independent of the asynchronous page feature, although the two can be used together for a pretty compelling asynchronous story.
Without further ado, here's an example of making three outbound asynchronous calls to a Web service called 'Slow', that simply sleeps for 3 seconds and returns. When run serially, this obviously takes a little more than 9 seconds to complete. However with asynchronous tasks, all three Web service calls come back in just over 3 seconds in true parallel fashion.
public partial class SlowMultiAsync : Page
{
Slow slowWebservice = new Slow();
protected void Page_Load(object sender, EventArgs e)
{
PageAsyncTask task1 =
new PageAsyncTask(
new BeginEventHandler(BeginGetAsyncData),
new EndEventHandler(EndGetAsyncData),
new EndEventHandler(TimeoutGetAsyncData),
"task1", //this is supplemental state (an object parameter) in which you can pass anything
true); //this is whether you want to run in parallel or serially
PageAsyncTask task2 =
new PageAsyncTask(
new BeginEventHandler(BeginGetAsyncData),
new EndEventHandler(EndGetAsyncData),
new EndEventHandler(TimeoutGetAsyncData),
"task2",
true);
PageAsyncTask task3 =
new PageAsyncTask(
new BeginEventHandler(BeginGetAsyncData),
new EndEventHandler(EndGetAsyncData),
new EndEventHandler(TimeoutGetAsyncData),
"task3",
true);
RegisterAsyncTask(task1);
RegisterAsyncTask(task2);
RegisterAsyncTask(task3);
}
IAsyncResult BeginGetAsyncData(Object src, EventArgs args,
AsyncCallback cb, Object state)
{
return slowWebservice.BeginHelloWorld(cb, state);
}
void TimeoutGetAsyncData(IAsyncResult ar)
{
Response.Write("<strong>async get data timed out</strong><br />");
}
void EndGetAsyncData(IAsyncResult ar)
{
string ret = slowWebservice.EndHelloWorld(ar);
// use result to prepare response here...
}
}
Again, note that you can combine this with the async page feature I discussed in a previous post, and not only will the tasks be issued concurrently, but they will not block a request thread while doing so - the best of both worlds in this case.
I'll follow up with more details of the implementation and some test results in the future, but I thought I'd share this now for those of you wondering if there would be support for concurrent tasks.
Posted
Feb 14 2005, 06:31 AM
by
fritz-onion