Reliably stop System.Threading.Timer?

2019-01-13 17:18发布

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

11条回答
我只想做你的唯一
2楼-- · 2019-01-13 17:44

An easier solution might to be to set the Timer never to resume; the method Timer.Change can take values for dueTime and period that instruct the timer never to restart:

this.Timer.Change(Timeout.Infinite, Timeout.Infinite);

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 using Timeout.Infinite should suffice.

查看更多
Viruses.
3楼-- · 2019-01-13 17:46

The MSDN Docs suggest that you use the Dispose(WaitHandle) method to stop the timer + be informed when callbacks will no longer be invoked.

查看更多
叼着烟拽天下
4楼-- · 2019-01-13 17:52

You can stop a timer by creating a class like this and calling it from, for example, your callback method:

public class InvalidWaitHandle : WaitHandle
{
    public IntPtr Handle
    {
        get { return InvalidHandle; }
        set { throw new InvalidOperationException(); }
    }
}

Instantiating timer:

_t = new Timer(DisplayTimerCallback, TBlockTimerDisplay, 0, 1000);

Then inside callback method:

if (_secondsElapsed > 80)
{
    _t.Dispose(new InvalidWaitHandle());
}
查看更多
迷人小祖宗
5楼-- · 2019-01-13 17:53

Perhaps you should do the opposite. Use system.timers.timer, set the AutoReset to false and only Start it when you want to

查看更多
迷人小祖宗
6楼-- · 2019-01-13 17:54

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.

查看更多
我命由我不由天
7楼-- · 2019-01-13 17:54

There is a MSDN link how to achieve stop timer correctly. Use ControlThreadProc() method with HandleElapsed(object sender, ElapsedEventArgs e) event synchronized by syncPoint static class variable. Comment out Thread.Sleep(testRunsFor); on ControlThreadProc() if it is not suitable(probably). The key is there that using static variable and an atomic operation like Interlocked.CompareExchange on conditional statements.

Link : Timer.Stop Method

查看更多
登录 后发表回答