如何避免同时执行后续的预定回调?

时间:2012-09-17 17:12:39

标签: c# .net multithreading timer

有关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()方法后不会发生回调。我的猜测是否正确?

1 个答案:

答案 0 :(得分:1)

其中一种方法是切换到System.Timers.Timer。我在博客上写道:

http://netpl.blogspot.com/2010/05/systemwindowsformstimer-vs.html

(条目的第二部分)