Often developers ask how to add polling, scheduled tasks and so on to ASP.NET web applications. There are many ways how to do it and there are even more reasons why not to do it. Let’s see what are the problems and how to build services for your web applications wherever they run.
IIS and web applications
IIS is the host of web applications. It knows how to handle requests and what modules to invoke to turn request to response. There are ASP.NET, PHP, PERL and many more applications available and IIS doesn’t know much about their specifics. In this means IIS is layer up from web applications running under it.
IIS also takes care of application pools, web server security, resource management and performance. Of course, we can configure IIS by our needs but not always – there are shared hosting and corporate environments where we don’t have much control so we have to live under technical limits that environment sets.
The classic example is something like this:
public class MvcApplication : HttpApplication
private static Timer _timer;
protected void Application_Start()
_timer = new Timer(MyCallback);
private static void MyCallback(object state)
// do something
Now let’s see what happens when we try to add our polling thread to web application.
After deploying our web application to server we can admit that application and specially our polling thread works okay. Even after some hours everything is okay but then in the evening suddenly we get a call because somebody noticed that polling doesn’t work anymore. We take a look at application and see that polling works. Also guy on the phone agrees that yes, it is working. What happened?
Your web application is considered to be active until it serves requests. After some idle time IIS considers your web application to be inactive and it unloads it from memory. The fact that your timer thread was active and something went on is not the problem of IIS because web applications are there to handle requests coming from web.
Of course, you can set IIS not to unload your application but you can do it onlyif you have access to IIS settings. Don’t be sure that administrators of shared hosting services make your application never unload.
Tombstoning aka suspending
Lately support for tombstoning of web applications was announced by Microsoft. What it means? Web application is not classically unloaded from memory but its memory image is saved to disc. When request comes in then this memory images is loaded back to memory and your application continues running.
Tombstoning of applications is way faster than loading and unloading. In near future this feature will probably be in mainstream use as it provides performance raise of web server up to 70% by Microsoft documents. Don’t expect hosting companies to ignore this feature.
As tombstoning also happens on IIS level then again it is possible you don’t have control over it. As tombstoning also means that your application stops working then you can be sure that your polling thread goes down too.
I can still keep my application running!
Yeah, it’s not a problem to write service that makes request to web application after every minute and this way guarantee that web application is never loaded or tombstoned. Your polling timer thread runs until your service is up and has connection to internet.
With solution like this you are far from stable and you have more things to worry about. Is my service running? Does it have network connection? Can it reach web application? Can I be sure that my service is asking resource that is handled by script engine in IIS?
Whatever hacks you do you cannot be sure that these hacks are solution.
What is the solution?
The best solution is to understand that web application is there to handle requests and it is not by nature like Windows service or task scheduler. Instead of mixing conceptually different functionalities to container that is perfect fit for only one context doesn’t end up well and you are far away from stability. Worse yet, mixing contexts may end up performance optimizing trap – if you improve performance of code in one context then code in the other context may lose a lot in performace.
Use Windows services or Windows task scheduler if you need to poll or run tasks regularly. You can add simple web service to your web application if data is needed by service and you don’t have to go and mess with web server settings. If your code is correctly layered then you can later move web services code to another web project and run in independetly of web application that serves your users.
For short, don’t mix contexts together and don’t hack. Use right tools for your job and you get way better and stable systems. Let web applications serve requests and let services do their job in their context.
View Comments (7)
Thanks for this article. I was already aware of the problems that can arise from using threads in a web application, however I'm not really sure how to handle such a case as good as possible:
Web application lists events, users can favorite events and should get an email notification when the registration period begins (as close to the actual time as possible).
Currently I'm leaning to this way: Webapp writes to a PendingNotifications table (UserId | EventId | Type | NotificationDate) and a console script is run by task scheduler every minute to fetch all "expired" pending notifications, execute them and delete the notifications from the table.
Are there any arguments against this behaviour or better ways to solve this? I know about Quartz.Net but I think it might be a bit overkill for this.
As far as you can be sure that console script works and it is run by scheduler with no exceptions and errors you can go with this solution. Personally I prefer Windows services but I also use shell scripts etc with Windows scheduler and I have no complaints.
I think this will change as WebSockets become an increasing part of web applications. The need to push updates to the browser in absence of a client request will spur the next development of web frameworks.
Aware of this? http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx
Yes, I know this post. Although it shows how to implement background tasks safest way I still don't that background tasks should be part of web application. My most important concern is that when application and "service" both grow then they must be usually scaled differently. Besides this I don't like the idea running web applications with full trust.
I tend to differentiate between a) Application Server (Long Running and Reliable) and b) Web Server (Shortliving and Scalable). IIS was not developed for a) but was introduced as hosting platform for WF (http://msdn.microsoft.com/en-us/magazine/gg535671.aspx). It's no recommended but exceptional implementations are possible and supported. If you abstract your "service-logic" there is nothing wrong with starting in IIS. and scaling to windows services.
I agree with you to point that you can start in IIS but I never recommend to do it when building applications with team. You can be 1000% sure that younger developers soon introduce bad dependencies between "service" and other parts of web application. Also it is better if customers know right from start that separate service is coming so their IT is prepared.