有关System.Threading.Timer
类的文档声明:
请注意,在调用Dispose()方法重载之后可能会发生回调,因为定时器将回调排队等待执行 线程池线程。
这意味着必须完成在调用Dispose()
方法之前调度的所有回调。但是如何安排回调?预定下一次回调是什么时候?
假设我们创建了一个Timer
类的新实例,其有限周期等于 P 且有限时间等于 D 。在 D 毫秒过后,将首次执行回调。从上一次回调开始的 P 毫秒后,将执行后续回调。编写代码示例,您将看到如果回调执行时间大于指定的时间 P ,则计时器将回调排队。
假设回调应备份文件中的一些数据:回调执行时间是备份执行时间,并且取决于必须写入文件的数据量,因此回调执行时间可能超过指定的时间段。在这种情况下,更适合在当前备份结束时安排下一个备份:为此,只需禁用周期性行为(通过将周期设置为Timeout.Infinite
)并调用{{1回调结束时的方法,如下面的示例代码所示。
Change()
通过这种方式,似乎没有回调排队。我还注意到在最后一个调度之后立即调用// some private fields
private readonly object syncRootForTimer = new object();
private Timer backupTimer = new Timer(BackupCallback, null, 10000, Timeout.Infinite);
private bool isTimerDisposed = false;
// it performs timer shutdown
public void Shutdown()
{
WaitHandle disposed = AutoResetEvent(false);
lock(syncRootForTimer)
{
backupTimer.Dispose(disposed);
isTimerDisposed = true;
}
WaitHandle.WaitAll(new WaitHandle[]{ disposed });
// ...
}
private void BackupCallback(object state)
{
// It performs the backup procedure...
// ...
lock(syncRootForTimer)
{
if (!isTimerDisposed)
backupTimer.Change(10000, Timeout.Infinite);
}
}
方法(即在最后一次调用Dispose(WaitHandle)
方法之后),甚至没有执行最后一个调度,并立即处理定时器。
我想我可以说禁用周期性行为并在回调执行结束时更改到期时间,定时器不会回调。这应确保在调用Change()
方法后不会发生回调。我的猜测是否正确?
答案 0 :(得分:1)
其中一种方法是切换到System.Timers.Timer
。我在博客上写道:
http://netpl.blogspot.com/2010/05/systemwindowsformstimer-vs.html
(条目的第二部分)