Well I've searched a lot for a solution to this. I'm looking for a clean and simple way to prevent the callback method of a System.Threading.Timer from being invoked after I've stopped it.
I can't seem to find any, and this has led me, on occassion, to resort to the dreaded thread-thread.sleep-thread.abort combo shudders.
Can it be done using lock? Please help me find a good way to do this. Thanks
An easier solution might to be to set the
Timer
never to resume; the method Timer.Change can take values fordueTime
andperiod
that instruct the timer never to restart:Whilst changing to use
System.Timers.Timer
might be a "better" solution, there are always going to be times when that's not practical; just usingTimeout.Infinite
should suffice.The MSDN Docs suggest that you use the
Dispose(WaitHandle)
method to stop the timer + be informed when callbacks will no longer be invoked.You can stop a timer by creating a class like this and calling it from, for example, your callback method:
Instantiating timer:
Then inside callback method:
Perhaps you should do the opposite. Use system.timers.timer, set the AutoReset to false and only Start it when you want to
You can't guarantee that your code that supposed to stop the timer will execute before timer event invocation. For example, suppose on time moment 0 you initialized timer to call event when time moment 5 comes. Then on time moment 3 you decided that you no longer needed the call. And called method you want to write here. Then while method was JIT-ted comes time moment 4 and OS decides that your thread exhaust its time slice and switch. And timer will invoke the event no matter how you try - your code just won't have a chance to run in worst case scenario.
That's why it is safer to provide some logic in the event handler. Maybe some ManualResetEvent that will be Reset as soon as you no longer needed event invocation. So you Dispose the timer, and then set the ManualResetEvent. And in the timer event handler first thing you do is test ManualResetEvent. If it is in reset state - just return immediately. Thus you can effectively guard against undesired execution of some code.
There is a MSDN link how to achieve stop timer correctly. Use
ControlThreadProc()
method withHandleElapsed(object sender, ElapsedEventArgs e)
event synchronized bysyncPoint
static class variable. Comment outThread.Sleep(testRunsFor);
onControlThreadProc()
if it is not suitable(probably). The key is there that using static variable and an atomic operation likeInterlocked.CompareExchange
on conditional statements.Link : Timer.Stop Method