Kicking off asynchronous processes from an ASP.NET page

Sometimes you need to kick off long running tasks from within an ASP.NET page. There’s plenty of examples out there showing you how to get the results of a Web Request (useful if you are calling a web service, for example) or if you are making a database call through one of the provided methods in ADO.NET, but it was not very easy to find a good source of information on what is needed when you want to provide that functionality for your own long-running methods. So the setup is: You have an ASPX page calling down to your Business layer and your Business method takes a while to do what you asked it to do before it comes back. So it would be nice if you are able to spend that time allowing your page to do everything else that it needs to do. Once the page is done with all other processing, the thread gets put on hold and allows other resources to be processed by the server and then the thread gets signaled when the long-running task completes and that causes the page to finish processing and return control back to the user. NOTE that the user can’t move on and do other stuff in the meantime, there’s other patterns for that (ie. polling), which is not what this is for.

Before:

Business layer method:

public string LongRunningTask(string inputValue)
{
  Thread.Sleep(30000);
  return "result";
}

aspx code snippet (Action initiated by a button on the screen:

protected void btnRequest_Click(object sender, EventArgs e)
{
  .
  .
  .
  string _Result = new Business.Utility().LongRunningTask("blah");     .
  .
  .
}

So in this case, the return would come back after 30 seconds, and any additional functionality would wait for that statement to complete. This is what we need to do in order to make this an asynchronous call:

After:

Business layer:
– Create a delegate for your long-running method:

public delegate string LongRunningTaskDelegate(string inputValue);

– You add “Begin” and “End” methods, using the IAsyncResult interface:

public IAsyncResult BeginLongRunningTask(string inputValue, AsyncCallback callback, object asyncState)
{
   return new LongRunningTaskDelegate(LongRunningTask).BeginInvoke(inputValue, callback, asyncState);
}
public string EndLongRunningTask(IAsyncResult ar)
{
  return ((LongRunningTaskDelegate)((AsyncResult)ar).AsyncDelegate).EndInvoke(ar);
}

aspx code:

protected void btnRequest_Click(object sender, EventArgs e)
{
  .
  .
  .
  Page.RegisterAsyncTask(new PageAsyncTask(new BeginEventHandler(BeginLongRunningTask),
                                               new EndEventHandler(EndLongRunningTask),
                                               null,
                                               true));
  .
  .
  .
}

The four parameters for PageAsyncTask are the Begin Handler, End Handler, Timeout Handler, and your object state. You can get pretty creative on how you use this in your own environment, and it will help you get a little bit more throughput out of your pages.

Scroll to Top