I have a Windows Service implemented in C# that needs to do some work every so often. I've implemented this using a System.Threading.Timer with a callback method that is responsible for scheduling the next callback. I am having trouble gracefully stopping (i.e. disposing) the timer. Here's some simplified code you can run in a console app that illustrates my problem:
const int tickInterval = 1000; // one second timer = new Timer( state => { // simulate some work that takes ten seconds Thread.Sleep( tickInterval * 10 ); // when the work is done, schedule the next callback in one second timer.Change( tickInterval, Timeout.Infinite ); }, null, tickInterval, // first callback in one second Timeout.Infinite ); // simulate the Windows Service happily running for a while before the user tells it to stop Thread.Sleep( tickInterval * 3 ); // try to gracefully dispose the timer while a callback is in progress var waitHandle = new ManualResetEvent( false ); timer.Dispose( waitHandle ); waitHandle.WaitOne(); The problem is that I get an ObjectDisposedException from timer.Change on the callback thread while waitHandle.WaitOne is blocking. What am I doing wrong?
The documentation for the Dispose overload I'm using says:
The timer is not disposed until all currently queued callbacks have completed.
Edit: It appears that this statement from the documentation may be incorrect. Can someone verify?
I know that I could work around the problem by adding some signaling between the callback and the disposal code as Henk Holterman suggested below, but I don't want to do this unless absolutely necessary.
ServiceBase.OnStop. I want to make sure the timer is disposed and no callbacks are in progress before I let the service shut down. I also have other shut down code I need to run, and I don't want to do this until I'm sure the timer is completely gone.