Geeks With Blogs
Jeff Krebsbach

Every time I inherit a windows service, I see the same design pattern:


public void ServiceProcess()
            while (true)


The theory here is that we are processing a work queue which will receive items, and every five minutes we will check to see what work has arrived in the queue.  Do work, sleep five minutes, Do work, repeat.  The problem is that we are blocking the owning process thread for five minutes while we sleep.  If there is a request to stop the work thread while sleeping, we have no way to wake up the sleeping thread.  This can result in a thread abort exception, and if we try to start a new thread we have strange behavior where the initiating thread can collide with the thread that is currently running.  Instead, use a timer to handle sleeping -


System.Threading.Timer _timer1;
        public void ServiceProcess()
            System.Threading.TimerCallback tcb = new System.Threading.TimerCallback(Foo);

            _timer1 = new Timer(tcb, null, 0, 300000); // Start immediately, wait 5 minutes between executions

 private void Foo(object stateInfo); // Method signature must take state object which is then parsed


To stop the process from executing, update _timer1 to prevent the callback from executing. 


Likewise if we want to have more control over when the process executes, we can directly modify _timer1 to start the process immediately.  Much cleaner.


Posted on Wednesday, September 8, 2010 6:58 PM | Back to top

Comments on this post: A better way for service threads

# re: A better way for service threads
Requesting Gravatar...
This is very important stuff for implementation of windows services. A common gotcha here is that developers often drag-n-drop the wrong timer control onto the component tray of the service.

Be sure to use the Timer from System.Threading.Timer (as Jeff does above)and NOT from System.Windows.Forms.Timer as the latter is not suited for multi-threaded / MTA environments like with the Windows Service.
Left by Jaans on Sep 09, 2010 2:29 AM

# re: A better way for service threads
Requesting Gravatar...
What's wrong with a WaitHandle that gets signaled both when shutdown has been requested or an item is added to the queue?

Agree with your larger point though - Using Thread.Sleep is a strong no-hire signal.
Left by James on Sep 09, 2010 3:12 AM

# re: A better way for service threads
Requesting Gravatar...
Also, if it wasn't clear, replacing Thread.Sleep with WaitHandle.WaitOne() which means effectively zero lag between an action occurring that the thread needs to handle, and the thread waking up to handle that action.
Left by James on Sep 09, 2010 3:14 AM

# re: A better way for service threads
Requesting Gravatar...
I prefer using events (Ex: using FilesystemWatchter) instead of timers.

If using timers:

* The duration of Foo() may be longer than the timer interval.
Thus I do restart the timer at the end of Foo() instead of using an interval.

* The proccessing in Foo() should check for stop requests to enhance process managebility. Otherwise the SCM might kill the service on shutdown instead of gracefully shutting it down.


Private _pollTimer as new Threading.Timer(Sub() Foo())
Private _isStopRequested As New ManualResetEvent(False)
Const _pollInterval = 300 * 1000

Sub OnStart()
_pollTimer.Change(0, Timeout.Infinite)
End Sub

Sub Foo()
If _isStopRequested.WaitOne(0) Then Exit Sub
Dim files = GetAllFilesSortedByLastAccess(WatchPath, FileNameFilter)
Do While files.Count > 0 And Not _isStopRequested.WaitOne(0)
For Each fileinfo In files
files = GetAllFilesSortedByLastAccess(WatchPath, FileNameFilter)
_pollTimer.Change(_pollInterval, Timeout.Infinite)
End Sub

Sub OnStop()
End Sub

Left by Peter Meinl on Sep 09, 2010 6:44 AM

# A better solution
Requesting Gravatar...
Instead of using timers, use ThreadPool.RegisterWaitForSingleObject because it utilizes IOCP threads.

Read about it here -
Left by Wayne B on Sep 09, 2010 10:34 AM

Your comment:
 (will show your gravatar)

Copyright © jkrebsbach | Powered by: