|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionProcessing 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. BackgroundArchitecturally 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 IHttpHandler and IHttpAsyncHandler: A Quick LookAll request execution in ASP.NET happens through the /*
Class Definition for System.Web.UI.Page
*/
public class Page : TemplateControl, IHttpHandler
The For this type of scenario, it is better to use the A Poor Man's Guide to Threading in ASP.NETThere are three simple ways you can accomplish threading within your ASP.NET application:
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 CodeThe 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
Most of the core logic takes place within the /// <summary>
/// Uses the IAsyncResult object to call a web service and writes
/// back the response to the caller
/// </summary>
public void Process()
{
try
{
// Get the zip code from the AsynRequestResult object
string strZip = Result.AsyncState as string;
int zipCode = Int32.Parse(strZip);
// Get the weather information
string message = Result.GetWeather(zipCode);
// Write back to the client
Result.Context.Response.Write(message);
}
finally
{
// Tell ASP.NET that the request is complete
Result.Complete();
}
}
The actual call to the weather web service under the ///<summary>
/// Gets the current weather information based on a US Zip code
/// </summary>
/// <param name="zipCode">City zip code</param>
/// <returns>Location name along with current temperature.
/// Empty string otherwise.</returns>
public string GetWeather(int zipCode)
{
string message = "";
try
{
// Call the web service
ExtendedWeatherInfo info =
weatherService.GetExtendedWeatherInfo(zipCode);
// Format the message
message = string.Format("<h2>{0} - {1}" +
"</h2>Current Temperature: {2}a<br>Feels Like: {3}.",
zipCode.ToString(), info.Info.Location,
info.Info.Temprature, info.Info.FeelsLike);
}
catch
{
message = "An error was encountered while calling web service.";
}
return message;
}
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 IETo make an HTTP request programmatically through JavaScript, you need to use XMLHTTP. For quite some time, Microsoft had bundled a version of this technology within their MSXML parser. To create a JavaScript object that binds to this feature, you do the following: var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
This function will make a full asynchronous request to a URL and attach a callback function: /*
Creates a XMLHTTP async-call to an ASP.NET async handler
*/
function postRequest(url)
{
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
// 'true' specifies that it's a async call
xmlhttp.Open("POST", url, true);
// Register a callback for the call
xmlhttp.onreadystatechange =
function ()
{
if (xmlhttp.readyState == 4)
{
var response = xmlhttp.responseText;
divResponse.innerHTML += "<p>" + response + "</p>";
stopProgressBar();
}
}
// Send the actual request
xmlhttp.Send();
}
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:
The final result from this process looks like:
ConclusionHaving 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. ReferenceDuring my writing of this article, I used the following resources:
|
||||||||||||||||||||||