AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=1778&pId=-1
Executing Asynchronous Tasks in ASP.NET
page
by Andrea Colaci
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 38222/ 65

Introduction

In this article I want to show three different ways to deal with long running tasks in ASP.NET.
If such a task must be initiated from an ASP.NET web page, the thread that is serving the page request is bound to the task until it completes or a timeout occurs. ASP.NET and .NET Framework offer different ways to address this issue. In the project used for this article, a sample page attempts to star a long running task in three different ways.

1. Synchronously simply starting the task and waiting for its completion
2. Asynchronously, using PageAsyncTask and other features
3. Asynchronously, using Asynchronous Delegates

Each of these options have pro and cons, and fit in different scenarios, but also these options do not require including the Async="true" attribute in the page's @Page directive.

The first option entails to keep busy the thread that is serving the request until the task completes. This could be a bottleneck, especially if multiple users start multiple tasks. This condition will probably end up to a 503 "Server Unavailable" error.

In this article I have used a sample web page that can start the same long-running task in three different ways.

Figure 1 - Sample page used in tests

Starting asynchronous task using PageAsyncTask

It is advisable to start a new thread that will perform the task, allowing the first thread to return in the thread pool and stand-by to serve a new incoming request.

To reach our goal, no modifications are required to the actual codebase that is in charge to execute the task. In the second option we are going to use a Page's method that first registers an async task, passing three different event handlers: one to begin/launch the task, one to manage its completion and the last one used to recover from a timeout that may occur during the task execution.

This option also uses IAsyncResult interface described here, but no extra coding is needed to use it, take a look to the code sample.

The SimpleWorker class exposes one method that simulates a long running operation, but it only writes a text line into a log file and waits one second per each line. Imagine an order's fulfillment procedure that creates packing lists and sends an email to customers indicating that their orders are "approved."

Listing 1 - Using PageAsyncTask

PageAsyncTask task = new PageAsyncTask(OnBegin, OnEnd, OnTimeout, null);
Page.RegisterAsyncTask(task);
TraceStatusInfo("TEST CASE #2: Start a long running task asynchronously using 
PageAsyncTask.");
//Setting up a 5 secs timeout
Page.AsyncTimeout = new TimeSpan(0, 0, 5);
TraceStatusInfo("Starting task");
Page.ExecuteRegisteredAsyncTasks();

If such a procedure is started from an ASP.NET page, it is a good practice to maintain an activity registry or log because the web application could be suddenly stopped without any warning and the worker process may be recycled due to excessive and unexpected resource consumption.

Starting asynchronous task using asynchronous delegates

The third option is the simplest one; it just uses an asynchronous delegate to start the task before sending the response to the client. When the client browser renders the page after the postback, the task is still running into another thread on the server and the original thread, that initially served the request, is now free and returned in the thread pool. You could look at the ThreadID into the SimpleWorker's log file and compare the server time when logging entries were added.

Listing 2 - Using asyncronous delegates

TraceStatusInfo("TEST CASE #3: Start a long running task asynchronously using an 
asynchronous delegate.");
SimpleWorker w=new SimpleWorker();
atd2 = new AsyncTaskDelegate(w.DoWork);
TraceStatusInfo("Starting task");
atd2.BeginInvoke(int.Parse(txtUnits.Text), null, null);
litStatus.Text = "Test #3 completed.";

The difference between the two last approaches is on the fact that the former can get the task result as it completes and informs the user, the latter must poll the server to see what had happened, this should not be an issue for some scenarios. However, an Ajax script could periodically hit the server querying an activity registry, like a table or a file, until the task is successfully completed. The second option could also benefit from the timeout handler; the third option instead is best suited for fire and forgets tasks.

Here is a snapshot of the log file in which you can see that TreadID changes when an async task is executed in tests cases #2 and #3.

Figure 2 - SimpleWorker's log file

 

Downloads
References
Conclusion

In this article you have learned the different ways to execute asynchronous tasks in ASP.NET leveraging built-in Page's methods and asynchronous delegates.


Product Spotlight
Product Spotlight 

©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-28 10:56:23 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search