Exploring all things .NET and beyond...

Running a Periodic Process in .NET using a Windows Service

The need does arise from time to time (literally) to process some repeated task in .NET. This question comes up a lot and about the best way of solving this problem. Should I poll repeatedly? Do I use a timer? What kind of timer should I use? etc...

Usually this question comes up when the need arises to do any of the following examples: checking for new information, reporting, sending emails, updating content on a screen, maintenance, and the examples go on and on.

I prefer to relegate this type of task to a Windows Service. The service can be created using Visual Studio .NET and then installed on your machine or server. The service is always running (once started) and provides a good mechanism for preforming repeated background tasks like periodic execution.

After doing research on this topic myself, I have found the best way to have a process run on a set time interval is to use a 'ThreadPool.RegisterWaitForSingleObject' from the System.Threading namespace. As from the
MSDN on this method: "Registers a delegate to wait for a WaitHandle, specifying an integer for the time-out in milliseconds."

The 'RegisterWaitForSingleObject' method registers a delegate to wait for a WaitHandle, specifying a timeout. It allows this service to tell the thread pool, "Hey, could you call me when this object is signalled or the timeout has elapsed? Thanks." The method queues the specified delegate to the thread pool (The thread pool uses background threads). A worker thread will execute the delegate when one of the following occurs:

-The specified object is in the signaled state.
-The time-out interval elapses.

This method will repeatedly call the delegate each time the timespan value has elapsed, or until the 'Unregister' method has been called. The callback method registered can do anything you need. The actual method will probably be local to the service, but from there you could make a call to a .dll, WCF or .asmx service, etc. to reuse existing functionality that may already exist. You just need the Windows Service to the the work of waking up every so often to do some work.

You can implement 1:many of these delegates to run as few or as many repeated tasks from within a Windows Service. I must give credit to the following Blog entry which really helped get me started with using this method: Periodic Execution in .NET <<--Code

The blog link above has a terrific easy to follow code example with explanations of implementing the RegisterWaitForSingleObject within a Windows Service, so I will not duplicate it here. I will just say that I myself have implemented the code and expanded on it, and can say that this is a great way to handle repeated processing of a task on a set time interval.

And lastly, you might be saying "I don't know how to create and use a Windows Service in .NET!". Well to get you going on that (there are quite easy by the way to get up and running), check out the following site:

Walkthrough: Creating a Windows Service Application in the Component Designer


Pete Chen said...

Hi Allen,

Great post and reference. Wonder how you think of a scheduled task that needs to be called once a week or biweekly? Do you still recommend using Windows Service? If yes, why? Thanks.


Allen Conway said...

@Pete - you still could use this method if you like or are familiar with it. In that case what I would do is have the elapsed time set to say every day and then check against, current date, day of week, date in database, etc. for equality and then run the process.

It's a bit brute force that way though and I only mention it if you want to use this method.

An alternative is to create a console app in .NET (instead of a Windows Service) that produces a .exe and use Windows Task Scheduler to set up the exact date and time for the .exe to be ran. In either case you could refactor out 'core' logic into a remote WCF or other service that gets called by the Win service or console app.

The last method might be to use SQL CLR code and a SQL job to kick off the process. I'm not a big fan of SQL CLR code as it is difficult to debug and test and not a lot of fun to work with. I think it was intended as a tool for offloading small pieces of logic TSQL couldn't handle (or handle well), but often it's abused and huge amounts of code are written.

So there you have a few ways this could be accomplished on a larger interval.

Pete Chen said...

Thanks for your comment. It's quite useful.

Anonymous said...

this post really helped me. thanks for taking the time to write.

Viet Doan said...

Thanks your post


Post a Comment