Skip navigation.

Book Review: Improving .NET Application Performance and 
ScalabilityAll recent postsBook Review: Joel on Software

Synchronous or Asynchronous Pages?

I see discussions about asynchronous web pages pop up more and more often these days. I attribute it to the anticipation that ASP.NET 2.0 makes this asynchronous hoopla easier to deal with. Let’s quickly review when asynchronous pages aren’t a good idea after all.

Some advocates of asynchronous handling of ASP.NET requests see it as the next best thing to improve performance of web applications. This claim holds true only in certain scenarios, though.

When a request to service a page comes in, it’s handled on a thread pool thread (a bit of funny terminology there for ya). If you hold on to it too long, you hit a page timeout. You can jack up the timeout, but you only hurt performance because the number of threads in the thread pool is limited, and the longer you hold on to one, the fewer requests your web app can service.

An ideal situation for an asynchronous call is when you have a “fire and forget” operation. You draw a new thread from the thread pool thread and delegate this long-running operation to it, and at the same time you let go of the thread processing the web request and let it complete. Say, a time consuming import or export operation is a good candidate.

Here’s another situation. You read a giant dataset and then do some transformations on it. Suppose all this takes too long, you exceed the timeout and your request gets recycled. Your users see a “white page” due to the timeout. It is tempting to take a thread from the thread pool and have it perform the looooooong read, but the thread—on which the request came—would have nothing to do. It’ll have to wait. So now you’re wasting 2 threads (!), not one. Asynchronous processing backfired.

To my point, here’s a valuable advice offered by the fabulous book Improving .NET Application Performance and Scalability (Chapter 5, page 217):

Avoid asynchronous calls that will block multiple threads for the same operation. The following code shows an asynchronous call to a Web service. The calling code blocks while waiting for the Web service call to complete. Notice that the calling code performs no additional work while the asynchronous call is executing.

[… sample code follows (see below) …]

When code like this is executed in a server application such as an ASP.NET application or Web service, it uses two threads to do one task and offers no benefit; in fact, it delays other requests being processed. This practice should be avoided.

The code in question is this:

// get a proxy to the Web service
customerService serviceProxy = new customerService ();

//start async call to CustomerUpdate 
IAsyncResult result = serviceProxy.BeginCustomerUpdate(null,null); 

// Useful work that can be done in parallel should appear here 
// but is absent here
// wait for the asynchronous operation to complete
// Client is blocked until call is done
result.AsyncWaitHandle.WaitOne();
serviceProxy.EndCustomerUpdate(result);

How Do You Deal With Long Running Operations?

One way is to design some kind of a broker, have it queue calls and let it process them as threads in the thread pool become available. Check out How To: Submit and Poll for Long-Running Tasks.

If you still need to show the user a response immediately and can’t afford a please-wait page, then you’re on your own. If the culprit is a 10-join database read and your database is highly normalized, then think about somewhat denormalizing it so you can perform fast reads from a flattened structure. Another suggestion: consider message queuing.

In any case the final answer is: it depends. :) If this discussion went over your head, I want you to walk away with this much:

Avoid asynchronous calls that do not add parallelism.

Comments

Comment permalink 1 Bill Rappleye |
I have recently ran into this dilemma as I struggle to make a piece of our current asp.net application a bit more user friendly. We have built a reporting mechanism that can take two minutes or more just to process and create chart graphics after the data is retrieved (despite the database data retrieval being very fast), and so it can cause inpatient users to get a bit ansy.

However, your point about not using another thread to perform the work while blocking the initial request thread made it clear that we would not want to take that approach.

So, my question is: How can an ad-hoc reporting mechanism that may take more than a few seconds be handled in a more user-friendly way? I welcome any input/comments or questions to this subject...
Comment permalink 2 Milan Negovan |
Bill, the typical approach to presenting progress in a user friendly way is outlined in the mentioned how-to article.

You'd need to write a manager to queue long running requests and allow client side code to ping this manager on the server. Whether you employ asynchronous JavaScript, iframes with refresh headers, etc, is really up to you.
Comment permalink 3 Atish |
Hello everybody,

Here is somewhat different problem that I am facing. actually my task is to upload files to any FTP site and to show the progress of the file being uploaded byte by byte. I am using .NET 1.1. I have used simple threading for this. I have shown the progressbar on the separate form. whenever a new upload of file is there, then a new instance of this form is created and the progressbar page is shown. On this Progress bar page, I have used a thread that continues with the file upload. But my problem is that whenever a new file is uploaded while the first one is yet being uploding, the latest one continues and the previous one waits. and completes when the latest is completed. I want to show both of them going on at the same time. Can any body suggests something on this. Thank You.

Yours, Atish.
Comment permalink 4 Website Software |
I have an answer to both the Blog and Atich's question about uploads.

First of all, asynchronous assumes only one need....you need to free up a thread in the thread pool to handle more web requests. IIs and the web server generally contains around 20 (25 on server 2003) default threads. That can be changed in the server. But what generally happens is as you take away threads due to either long running processes or asynch calls that run in the background, you lose valuable threads to handle requests, so your request time from browser starts to inch up as volume increases. Its a losing game. I never use asynchronous for that reason.

The best way to handle this is to create a new non thread pool thread and start your new process. This gets fired and the rest of your web page completes processing and is sent bacl as a response like normal. Now, your long running process isnt done, but it can do its magic and complete as needed. Its doesnt run under the pool of threads but is a managed CLR thread that runs out of process. We have used this strategy to run calls to web services that need to complete things like emailing and database and file updates behind the scenes. This is much better than Asych, which does take two thread pool process.

Now, the essential question then becomes, "How do I tell the user and their browser Im done processing?". Well, thats the trade off....if you run a behind-the-scenes thread, you dont need to. If you need to tell them, you can combine an asynch web page with this out of process thread solution, and that should work, as long as you do Thread.Join, to make sure the Asynch page is locked and waiting for the other thread. But a better solution Ive found is with AJAX or a small bit of javascript. You can set a timer in your customers browser page in JScript and poll the server for the linked script file and in there store ASP.NET updates values stored as variables in JavaScript. This way, you can set a timer and keep siliently calling the server till its done processing, and tell the user, "hey, your process is done!".

Overall, people need to get away from thnking about asynchronous, as its not that great a solution. In the end, what your build yoruself is always superior to allot of the out-of-the-box stuff thats in ASP.NET.
Comment permalink 5 Milan Negovan |
Great points! Thank you for the comment.
Comment permalink 6 Martin |
This asynchronous stuff is boggling my mind

"It is tempting to take a thread from the thread pool and have it perform the looooooong read, but the thread—on which the request came—would have nothing to do. It’ll have to wait. So now you’re wasting 2 threads (!), not one. Asynchronous processing backfired."

Hi, this is what you said...and honestly doesn't make much sense since the request would be ready for another request from another user on the website and not as you said "would have nothing to do". Maybe I'm wrong, but surely would have nothing to do.. which is the whole idea to be.

The point of asynchronous paging is not to be more user friendly or not. To do the user it would look like pretty much the same but the long running process would be taken care by a non-request thread.

I could be I'm not understanding something. With Asynch processing ASP.NET provides, if the thread is not taken from those 25 request threads, from where it is taken?

Thanks!
Comment permalink 7 Sergey |
Read this: http://msdn.microsoft.com/en-us/magazine/cc163725.aspx

Looks like Request thread is actually returned to the pool.

Emails and Notifications

Would you like to be notified when somebody responds to this post?  Would you like to have these comments emailed to you?

Submit your comment

Please enter only text since all HTML tags except hyperlinks will be stripped. Hyperlinks will become live links. Any comments with flaming or offensive language will be deleted. Be courteous to other posters. Thank you.

Your name (required):
Your email (optional):
Your site's URL (optional):
Enter this number
Type in the number above:
Comment (required):