我用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();
我在回调线程中使用timer.Change
时,会出现ObjectDisposedException
,而waitHandle.WaitOne
正在阻塞。我做错了什么?我所使用的
Dispose
重载的文档指出:“直到所有当前排队的回调完成之前,定时器才不会被处理。”
编辑:似乎文档中的这种说法可能是不正确的。有人可以验证吗?
我知道我可以通过添加一些信号来解决回调和清理代码之间的问题,就像Henk Holterman在下面建议的那样,但除非绝对必要,否则我不想这样做。
ServiceBase.OnStop
中进行计时器处理的。我想确保计时器被处理并且没有回调正在进行,然后才允许服务关闭。我还有其他关闭代码需要运行,但在确保计时器完全消失之前,我不想这样做。 - William Gross