任务执行时间高于定时器执行时间
问题描述:
我想澄清一下可能的代码实现,以防在使用timerDoJob_Elapsed
执行的代码变长时它应该如何。 所以当下次计时器启动时,所有的内部事物都会被篡改/取消等等。任务执行时间高于定时器执行时间
这种问题有什么模式吗? 任何线索,使其更加稳定?
private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e)
{
VeryLongTask1();
VeryLongTask2();
VeryLongTask3();
}
答
如果您使用System.Timers.Timer,关闭AutoReset。然后在Elapsed方法结束时重新启用计时器。
private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e)
{
VeryLongTask1();
VeryLongTask2();
VeryLongTask3();
mytimer.Enabled = true;
}
这样,定时器甚至不会再次启动,直到任务完成。但是请确保在try/catch块中的Elapsed方法中包含所有内容,因为如果发生未处理的异常,您的计时器将不会再次启动。
我以前用过的另一种方法是在你经过的事件,使用锁:
var myLock = new Object();
private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e)
{
lock (myLock) {
VeryLongTask1();
VeryLongTask2();
VeryLongTask3();
}
}
这样,经过的事件的两个实例不能在同一时间运行。但是,有一点需要注意:如果任务需要比定时器的两次或更多次迭代更长的时间,则可以在后台添加迭代。例如,如果您的计时器在5秒后过去了,但您的任务需要60秒才能完成,但在第一次完成时,您将有11次等待。
答
Timer.Change
方法给予Timeout.Infinite
和0
作为参数会停止计时器(从MSDN):
如果duetime参数是零(0),回调方法被立即调用。如果 dueTime是Timeout.Infinite,则永远不会调用回调方法; 定时器被禁用,但可以通过调用Change和 指定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);
}
}
你问,如果它怎么取消任务会持续太久? –
@SamIam不,我不是。其实任务应该及时完成,但下一次计时器的迭代不应该破坏以前的东西。 –