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)


Comments

Comments are disabled in preview mode.