How to create asynchronous ASP.NET pages using C#

IIS combined with ASP.NET provides many technologies to improve performance and scalability.  IIS provides a pool of threads so that it can server many requests simultaneously.  The pool has a limited number of threads in it, and once they are used up additional requests can start to pile up.  Keeping the total number of active threads down is an attempt to prevent too many active threads from consuming all of the available CPU time.  According to Andy Defrancesco with today’s data intensive websites, much of the time threads are tied up waiting for an external resource such as a request from a web service or from a database.  Asynchronous pages in ASP.NET can boost performance in these situations by enabling threads in the pool to be used to serve additional requests while an operation is waiting for an external resource request to complete.

Suppose you have a website with two web pages.  One is your home page which display’s a greeting, and the second page displays a large dataset from a database.  You have 25 threads in your thread pool.  25 people simultaneously are accessing the database query page, and one additional person comes onto the site to see the home page which has static content on it. And if your website sees high levels of traffic, consider switching to dedicated hosting plans to ensure that your site doesn’t slow down.

Compare these two scenarios:

Synchronous database driven page:  While everyone is waiting for the dataset to load, all available threads are in use so the 26th request for the home page becomes blocked.

Asynchronous database driven page:  While 25 requests are waiting for data from the database, those threads are returned to the pool for work.  When the 26th request comes in for the home page, that page is returned immediately.  As the datasets are returned the threads are drawn out of the thread pool to finish serving the pages.  The result is that the threads spend much more time available to serve requests.

Here are two good pages for getting started with asynchronous ASP.NET pages:

Asynchronous ASP.NET Page Processing by Peter Bromberg

Use Threads and Build Asynchronous Handlers in Your Server-Side Web Code by Fritz Onion

After reading these and some other articles, here is a piece of code to get you started.  I put this together to process a job in the background as a generic pattern.  I wrap my big job in a delegate so that I can get an IAsyncResult object back.  This simplifies things, because in most examples I read you get this by calling a web service asynchronously but this is’t always what you want done.

Step 1:  Make an empty page.  Add async=”true” to the @Page tag in the .aspx file.

Step 2:  In the class code, declare a delegate

public delegate void AsyncTaskDelegate();

Step 3:  Declare a member variable in the class to prevent the delegate from going out of scope

AsyncTaskDelegate _runnerDelegate = null;

Step 4:  Create a method that will be run asynchronously:

public void DoJob()


this.GridView1.DataSource = GetDatasetFromDatabase();        this.GridView1.DataBind();


Step 5:  Tell the framework you want your job run.  You can put this in Page_Load or in a response to a button click / postback:

// Register async methods


new BeginEventHandler(OnBegin),

new EndEventHandler(OnEnd)


Step 6:  Add the event to kick off the delegate and run the job asynchronously.

IAsyncResult OnBegin(object sender, EventArgs e, AsyncCallback cb, object state)


_runnerDelegate = new AsyncTaskDelegate(this.DoJob);

IAsyncResult result = _runnerDelegate.BeginInvoke(cb, state);

return result;


Step 7:   Add an event handler for after the request finishes

void OnEnd(IAsyncResult ar)




All together, it looks like this:

   1:  public partial class Async : System.Web.UI.Page
   2:  {
   3:      public delegate void AsyncTaskDelegate();
   5:      AsyncTaskDelegate _runnerDelegate = null;
   7:      IAsyncResult OnBegin(object sender, EventArgs e, AsyncCallback cb, object state)
   8:      {
   9:          _runnerDelegate = new AsyncTaskDelegate(this.DoJob);
  10:          IAsyncResult result = _runnerDelegate.BeginInvoke(cb, state);
  11:          return result;
  12:      }
  14:      public void DoJob()
  15:      {
  16:          this.GridView1.DataSource = new AsyncTaskDelegate(this.DoJob);
  17:          this.GridView1.DataBind();
  18:      }
  20:      void OnEnd(IAsyncResult ar)
  21:      {
  22:          _runnerDelegate.EndInvoke(ar);
  23:      }
  25:      protected void Button1_Click(object sender, EventArgs e)
  26:      {
  27:          // Register async methods
  28:          AddOnPreRenderCompleteAsync(
  29:              new BeginEventHandler(OnBegin),
  30:              new EndEventHandler(OnEnd)
  31:          );
  32:      }
  34:  }

Original Source:


Deepak Kamboj

Deepak Kamboj is a Solution Architect and Technology Enthusiast, located at Redmond, WA, having 14+ years of hands on experience in the IT industry.

You may also like...