Every time I inherit a windows service, I see the same design pattern:
public void ServiceProcess()
{
while (true)
{
Foo();
Thread.Sleep(300000);
}
}
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.
_timer1.Change(System.Threading.Timeout.Infinite,
System.Threading.Timeout.Infinite);
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.