任务执行时间高于定时器执行时间

时间:2016-04-29 19:12:48

标签: c# .net

如果执行timerDoJob_Elapsed的代码变得越来越长,我想澄清可能的代码实现。 因此,当计时器下次启动时,所有内部事物都会被解决/取消等等。

这种问题有什么模式吗? 有什么线索让它更稳定?

private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e)
{
     VeryLongTask1();
     VeryLongTask2();
     VeryLongTask3();
}

2 个答案:

答案 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.Infinite0作为参数的

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);
     }
}