Processing long running tasks (i.e., SQL query execution, Web Services calls, etc.) has always been an important feature for high demand web applications. One problem these applications face is that of keeping the client UI responsive as the task executes.
Many sites, like Expedia, Travelocity etc. use intermediate 'Please Wait...' pages to work around the problem. Other sites, like Google Maps use client-side features such as XMLHTTP to make such requests without moving the user from the current page. The purpose of this article is to show how to use XMLHTTP along with ASP.NET to make the end user experience a bit more tolerable.
Architecturally speaking, a key feature of ASP.NET is its objects have a short lifespan. This is extremely important to high demand web sites because it allows the application to execute quickly and efficiently and still be able to maintain a high level of concurrent users. The key factor behind keeping an ASP.NET web site responsive is to be aware of the framework constructs that control page execution.
A lot of developers know that to create a simple web page in ASP.NET one must use the
System.Web.UI.Page class. However, some of them might not be aware that there are other ways to handle requests made to the application. This is where
System.Web.IHttpAsyncHandler interfaces come into play.
IHttpHandler and IHttpAsyncHandler: A Quick Look
All request execution in ASP.NET happens through the
System.Web.IHttpHandler interface. If you look at the object diagram of the
System.Web.UI.Page class, you can see that it inherits from the
System.Web.UI.TemplateControl and implements the
System.Web.IHttpHandler interface. The class definition and object hierarchy looks like this:
public class Page : TemplateControl, IHttpHandler
IHttpAsyncHandler interface inherits from
IHttpHandler and defines two extra methods,
EndProcessRequest respectively. These methods make up the mechanism needed to handle asynchronous calls within ASP.NET.
For this type of scenario, it is better to use the
IHttpAsyncHandler rather than a
Page object because of all the extra work (child control rendering, event handler notification, etc.) the
Page performs per request. For more information on
IHttpAsyncHandler, please see the MSDN documentation.
A Poor Man's Guide to Threading in ASP.NET
There are three simple ways you can accomplish threading within your ASP.NET application:
- Using the
- Using a custom delegate and calling its
- Using custom threads with the aid of
The first two methods offer a quick way to fire off worker threads for your application. But unfortunately, they hurt the overall performance of your application since they consume threads from the same pool used by ASP.NET to handle HTTP requests. In other words, if you invoke five pool/delegate threads within a request, your application will only have 20 available threads remaining in its pool (by default, ASP.NET gives every application 25 worker threads). The way to get around this problem is to use the third option since the threads created are not part of your application's pool.
If you would like to read more on threading in ASP.NET, please see the References section.
Stepping Through the Code
The example used with this article is that of a simple weather service. The UI allows the user to enter US Zip codes to check current weather condition of cities. The reason why I chose a web service call is because it gives a great 'real world' example on how to use the asynchronous capabilities of ASP.NET and XMLHTTP.
When a user selects an entered zipcode from the list and hits the Check Weather button, two async requests are created, one to the weather checker handler and the other to the web service. A DHTML progress bar is used to keep the user 'entertained' while this process executes. Once a response is received by the client, the progress bar is stopped and the UI updated.
The main class behind this example is the
AsyncTaskHandler class. This class is mapped to an .ashx file so ASP.NET can hook up the request chain. This class implements two interfaces the
IHttpAsyncHandler, mentioned earlier, and the
System.Web.SessionState.IRequiresSessionsState interface that is used to tell ASP.NET that this handler has access to session state. The class then uses two classes
AsyncRequest to process the request.
AsyncRequestResult implements the
System.IAsyncResult interface so ASP.NET can call the appropriate methods necessary to perform a call back. The
AsyncRequest class is used to house a call to an external weather Web Service and write back the response to the waiting client. The collaboration between the objects can be seen by the following diagram:
- As soon as the handler receives a request, it creates an object of type
- Using this object as a constructor parameter, the handler then creates an object of type
- Finally, the handler creates a worker thread of type
System.Thread.Thread and uses the
Process method of
AsyncRequest and returns the created
AsyncRequestResult back to ASP.NET and a response to the client.
Most of the core logic takes place within the
AsyncRequest.Process method. Within this method, the associated
AsyncRequestResult object is used to make a call to the weather information web service and to return an HTML snippet back to the client. The method looks as follows:
The actual call to the weather web service under the
AsyncRequestResult.GetWeather method looks like:
Now that you have a quick overview of how the code works, let's see how the client creates the request and handles the response.
Using XMLHTTP Within IE
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
This function will make a full asynchronous request to a URL and attach a callback function:
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.Open("POST", url, true);
if (xmlhttp.readyState == 4)
var response = xmlhttp.responseText;
divResponse.innerHTML += "<p>" + response + "</p>";
From here, while we wait for the async handler to execute the long processing request, we show the users a simple little progress bar showing them that their request is being processed.
The following diagram shows how the execution of the request from XMLHTTP takes place:
XMLHTTP object is created when the user clicks on the Check Weather button.
- This object creates an async (non-blocking) request to weatherchecker.ashx.
- A temp callback is attached to the object to handle the response from the handler.
- Whenever the handler is finished executing the call to the web service, a response is generated back to the client's temp callback.
- The temp callback is executed in the client, the response text is set to a
<div>, and the progress bar is stopped.
The final result from this process looks like:
Having the ability of executing long running tasks asynchronously is a huge benefit for any web application regardless of size. I hope that this article shows developers an alternate way of tackling this design problem. Also, I hope that developers are more conscious when making decisions to add threading to their ASP.NET applications.
Please feel free to make any comments or suggestions to this article by using the forums below.
During my writing of this article, I used the following resources: