如果执行timerDoJob_Elapsed
的代码变得越来越长,我想澄清可能的代码实现。
因此,当计时器下次启动时,所有内部事物都会被解决/取消等等。
这种问题有什么模式吗? 有什么线索让它更稳定?
private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e)
{
VeryLongTask1();
VeryLongTask2();
VeryLongTask3();
}
答案 0 :(得分:1)
如果您正在使用System.Timers.Timer,请关闭AutoReset。然后在Elapsed方法结束时重新启用计时器。
private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e)
{
VeryLongTask1();
VeryLongTask2();
VeryLongTask3();
mytimer.Enabled = true;
}
这样,在任务完成之前,计时器甚至不会再次启动。但是请确保在try / catch块中包装Elapsed方法中的所有内容,因为如果在那里发生未处理的异常,则您的计时器不会重新开始。
我之前使用的另一种方法是在您的Elapsed事件中使用锁定:
var myLock = new Object();
private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e)
{
lock (myLock) {
VeryLongTask1();
VeryLongTask2();
VeryLongTask3();
}
}
这样,Elapsed事件的两个实例不能同时运行。但是,有一个警告:如果任务花费的时间超过计时器的两次或更多次迭代,那么您可以在后台添加迭代。例如,如果您的计时器在5秒后过去,但您的任务需要60秒才能完成,那么当第一个计时器完成时,您将有11个等待。
答案 1 :(得分:1)
Timeout.Infinite
和0
作为参数的 Timer.Change
方法将停止计时器(来自MSDN):
如果dueTime为零(0),则立即调用回调方法。如果 dueTime是Timeout.Infinite,永远不会调用回调方法;该 计时器已禁用,但可以通过调用更改和重新启用 为dueTime指定正值。
一种可能且简单但功能强大的方法是停止计时器直到整个任务结束,然后再次启动计时器:
private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e)
{
timerDoJob.Change(Timeout.Infinite, 0);
// Use a try-finally so if some tasks throws an exception
// the timer will be re-enabled again anyway
try
{
VeryLongTask1();
VeryLongTask2();
VeryLongTask3();
}
finally
{
timerDoJob.Change(0, 5000);
}
}