Most likely you all have experienced an annoying error when trying to open an internet address and that error is nothing except “Server too busy” error!
For ASP.NET applications one of the very common causes of this error is that the Thread Pool is full and can’t assign a new thread to new requests, so IIS can’t serve the new requests. The main reason is that there is a long-running process running on the server and this keeps the thread busy. Usually this isn’t a big concern because there aren’t many visitors/requests on the server or the Thread Pool can be set to use more threads to prevent such an issue.
Yesterday Scott Hanselman had hosted a live web chat session on TinyChat to discuss some topics and asked my opinion about the recent poll that he had published on Twitter about the usage of asynchronous web pages in ASP.NET WebForms and asynchronous controllers in ASP.NET MVC. I’ve been wanting to write about this (like many other topics) but as you may have noticed, I really don’t have enough time for blogging!
Generally speaking, the implementation of such techniques and the emphasis that some people put on these aspects of web development directly reflect the level of their experience and expertise. In my opinion this is one of the points that should be included in ASP.NET books and articles to enhance the level of knowledge among ASP.NET developers in order to improve the overall quality of ASP.NET web applications deployed to web servers.
I think that it’s been a weakness of the ASP.NET community for not spreading the word about these features and improve the level of awareness among normal ASP.NET developers. Although Scott’s poll gives very positive results, as he mentioned in the chat session, these results are likely to be based on the more professional level of developers of his followers and my personal experience is different.
As I told Scott, there are two important criteria for choosing this approach in your web applications:
- The existence of a long-running process such as I/O access or external resource request (i.e. HttpClient request from a third server) that have the potential to block the thread.
- Expectation of large number of requests/visitors on the application on production. This is something relative but I think every developer knows his to call something large!
If you think that your application has a chance to face with these problems, then it’s your duty to implement some kind of asynchronous request processing mechanism for your web application.
ASP.NET 2.0 introduced the concept of asynchronous pages to use the Thread Pool efficiently and this feature has existed in ASP.NET WebForms since then.
ASP.NET MVC lacked a straightforward equivalent mechanism in version 1.0, but asynchronous controller is one of the major additions to ASP.NET MVC 2.0 that you can implement to provide a higher level of efficiency and thread usage for your applications.
Besides these features, you also have access to asynchronous HttpModules and HttpHandlers both in ASP.NET WebForms and ASP.NET MVC.
ASP.NET Thread Usage on IIS 6.0 and 7.0
Thomas Marquardt has a good explanation about the differences between ASP.NET thread usage in IIS 6.0 and 7.0 which is directly related to asynchronous pages in ASP.NET WebForms and asynchronous controller in ASP.NET MVC.
In essence, in IIS 6.0 there is a request pool on IIS and then is handed over the CLR Thread Pool which releases the threads in IIS pool. At this point the CLR Thread Pool is responsible for managing the number of threads to handle the workload. Usually the CLR Thread Pool increases the number of threads for high latency threads.
Besides, there are other thread pools at the application level for each AppDomain. If ASP.NET runtime detects that there are too many threads running on the server exceeding a threshold set by minFreeThreads and minLocalRequestFreeThreads attributes in <httpRuntime />, then it moves the threads to the application level pool. Here note that the approach in IIS 6.0 was to restrict the number of concurrently executing threads. When the number of concurrency requests goes lower than the threshold, then the threads will be moved back to the main pool for execution. These application-specific pools were problematic and endured performance issues and forced Microsoft to remove them in IIS 7.0.
Now in IIS 7.0 integrated mode you don’t have any application-level pool. The other big difference is that in IIS 7.0 you restrict the number of concurrently executing requests rather than threads that you had in IIS 6.0. Normally, there isn’t any differences between these two and they have the same numbers unless you have asynchronous execution of requests, and in this case you have more requests than threads.
Although there are some restrictions applied in regards to backwards compatibility, this change in IIS 7.0 is very helpful for asynchronous request processing.
Asynchronous is not Faster
One common misconception about asynchronous operations in general and asynchronous pages/controllers in particular is that they make the request processing faster, but this is a wrong belief that people should erase from their minds because this is not necessarily true, and interestingly, in context of ASP.NET asynchronous pages/controllers this is always wrong.
The usage of asynchronous pages or controllers doesn’t change the time and resource needed for the request to be processed by the processor and I/O devices, so they take the same time to be processed. Instead, by using these features you let other threads to use the available resources when the original threads are idle and waiting for other operations to complete execution.
More interestingly, there is a chance that asynchronous processing makes the overall processing time a little slower because some time should be spent on switching between threads and this is a pure overhead that exists in all levels of Operating Systems.
All in all, it doesn’t hurt to use asynchronous pages or controllers in your applications. The thread switching time doesn’t seem to be very large and it’s safer to use this feature in your web applications rather than excluding it.
Hopefully, in two blog posts in the near future I’ll go over the implementation of asynchronous pages in ASP.NET WebForms and asynchronous controllers in ASP.NET MVC 2.0. I may also talk about asynchronous HttpModules and HttpHandlers as well.