All posts

Using an HttpModule to Run a Background Service

This is a great technique for those of you who need to run a service on your web server, but are using shared hosting and don't have the ability to do so. I first saw this technique at one of Rob Howard's TechEd sessions earlier this year.

If you have the need to do some routine processing, typically you would consider writing a Windows service. For example, if you were running a web application which pulls data from multiple other sites and web services you might want to periodically load that data into a database and serve it from there rather than pulling it from the web on each request. You could do this with a Windows service. However, using a service requires that you have unfettered access to the server operating system. This is typically not the case in a shared hosting environment. So what other options do you have? Well, you could revert back to simply pulling the data from external resources during each page request, or you could go fetch it during a routine event such as the start of a new session. But these options impact performance and force your users to wait while the data is retrieved. Instead, you can use an HttpModule to periodically grab a thread and do the work for you.


Background Service Demo

By way of example, I have built a simple application that uses Yahoo!'s weather RSS service to display my local weather to a web page. And rather than pulling the data from Yahoo! each time I make a request to the page, I created an HttpModule to do the work for me. In the HttpModule I declare 3 static variables: a System.Threading.Timer class to set the intervals at which I want to have some work done, a string to hold the retrieved data, and an object used as a semaphore to synchronize threads on my string.

0

When the HttpModule is initialized, I create a new static instance of the System.Threading.Timer class. It is important to note that there can only ever be one instance of the Timer class at any given time. This is important because otherwise I could easily burn through my available threads and really make a mess of my application. When instantiating the new Timer, I set its start time (immediately), its interval (10 seconds), and a callback method (DoWork) which will execute every time the interval expires. During initialization I also add an event handler, OnBeginRequest, to run when the BeginRequest event of the HttpModule is fired.

1

Each time the Timer's callback interval expires, the DoWork method is called. It is in this method that the work is done. In this instance, it pulls data from the external site, parses it, and saves it to a local static variable for easy retrieval. A lock is placed around the code to protect it from other threads who may be trying to read from or write to the static variable (_value) as well.

2

The OnBeginRequest method handles the BeginRequest event, which occurs as a new request enters the pipeline. It is at this point that I pass the stored data into the pipeline so that it is available further down the line.

3

Once the requested page is loaded, the data can be retrieved quickly and written out to the page.

4

5

Finally, in order to have the new HttpModule loaded up into the pipeline when a request comes in it must be declared in the web.config. When setting the type property, you must declare it as "Namespace.ClassName, AssemblyName"

6


Conclusion

The beauty about this technique is that it is simple to implement, can be easily included in your web application (and thus run in a shared hosting environment), and provides a solution to developers who have a need to run a service continually in the background. My example was just that - an example. This technique can easily be used for other processing that needs to be done: sending emails, retrieving data, processing queued jobs, etc.

For more information about creating HttpModules, check out this MSDN article. Also take a look at this recent blog post by Phil Haack, in which he shows how to use an HttpModule to measure the time it takes to process a request.

Source Code (C#)        Source Code (VB)

Facebook DZone It! Digg It! StumbleUpon Technorati Del.icio.us NewsVine Reddit Blinklist Furl it!

Comments  8

  • 25 Jul, 04:33 AM

    Excellent little snippet, i have some background tasks like build index / clearlog that i am going to schedule using this.

    Ismail Mayat

  • 25 Jul, 08:51 AM

    What would be the performance implications if I used the technique to run just once daily?

    Shaun Peet

  • 25 Jul, 11:15 AM

    Thanks for this tip. What about if IIS unloads the Web site instance from the application pool? Is the background automatically killed?

    Delf

  • 25 Jul, 11:19 AM

    An example... the Web application sends mails each hour. At present time I use Console application with scheduled tasks. Even if the Web application is unloaded from memory, the Console application gets access to the database to retreive data. What about with this tip? If the Web application is unloaded implies the task does not exist. Of course we can disable the fact that IIS unloads it...

    Delf

  • 26 Jul, 03:01 PM

    @Shaun: The The System.Threading.Timer callback request does not run in the same thread as the timer; instead, a thread is pulled from the thread pool to execute the callback request. So if you set the interval to 24 hours, you will only incur the cost of the timer until the callback request is executed, which is negligible.

    Kevin Babcock

  • 26 Jul, 03:06 PM

    @Delf: This example is probably more appropriate for developers who do not have access to the host operating system. If you can add a service or app on your server that performs the functionality you require, then that may be your best option. However, if you are using shared hosting, you will not have access to the operating system and this is a great option to run those batch jobs at regular intervals.

    To answer your question, if the web app is unloaded from the app pool then you will lose the HttpModule, resulting in the timer being garbage collected and your service no longer running. As you suggested you can ask IIS to never recycle the app.

    Kevin Babcock

  • 31 Jul, 01:14 PM

    Thanks for posting, I can use this!

    infocyde

  • 28 Dec, 03:56 AM

    Hi,

    Great Article !

    But the problem is that when IIS Worker Process got recycled the Application stops, so the Background Service too ...

    Anyway a great tip :)

    Thanks.

    Yoann. B

Post a comment!
  1. Formatting options
       
     
     
     
     
       
  2. Security image