我有一个用 C# 实现的 Windows 服务,它需要经常做一些工作。我已经使用 System.Threading.Timer
实现了这一点,该回调方法负责安排下一个回调。我无法优雅地停止(即处理)计时器。以下是您可以在控制台应用程序中运行的一些简化代码,可以说明我的问题:
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();
问题是当 waitHandle.WaitOne
阻塞时,我从回调线程上的 timer.Change
得到了一个 ObjectDisposedException
。我做错了什么?
The documentation对于我正在使用的 Dispose
重载说:
The timer is not disposed until all currently queued callbacks have completed.
编辑:看来文档中的此声明可能不正确。有人可以验证吗?
我知道我可以通过在回调和处置代码之间添加一些信号来解决这个问题,正如 Henk Holterman 在下面所建议的那样,但除非绝对必要,否则我不想这样做。
最佳答案
用这段代码
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 );
几乎可以肯定的是,您将在定时器休眠时对其进行 Dispose。
您必须在 Sleep() 之后保护代码以检测 Disposed 计时器。由于没有 IsDisposed 属性,快速而肮脏的 static bool stopping = false;
可能会成功。
关于c# - 如何优雅地停止 System.Threading.Timer?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12354883/