Winservice - Timer:同一任务正在并行执行

本文关键字:任务 并行执行 Timer Winservice | 更新日期: 2023-09-27 18:11:03

我做了一个windows - service,它在每个操作之后执行一个操作。我们已经这样声明了计时器:

using System.Timers;
....
Int32 myInterval = 60000 * (Convert.ToInt32(ConfigurationManager.AppSettings["lpInterval"].ToString()));
_myTimer = new Timer();
_myTimer.Interval = myInterval;
_myTimer.Elapsed += new ElapsedEventHandler(TimerElapsed);
    //Timer-Tick
private void TimerElapsed(object source, ElapsedEventArgs e)
{ PerformAction(); }

我注意到:如果PerformAction()需要的时间比interval长(由于WCF-Services或服务器问题),则启动并执行PerformAction的新'instance'。因此,PerformAction(和parallel)相互运行两次。

这是什么原因?为什么之前的PerformAction没有被取消?

方法PerformAction正在执行Async吗?

我已经找到了一个解决方案,但我只是不理解的行为…

Winservice - Timer:同一任务正在并行执行

在你运行动作之前停止计时器,然后在执行动作之后再次启动计时器

private void TimerElapsed(object source, ElapsedEventArgs e)
{ 
    _myTimer.Stop();
    PerformAction();
    _myTimer.Start();
}

系统。计时器

http://msdn.microsoft.com/en-us/library/system.timers.timer.elapsed (v = vs.110) . aspx

在ThreadPool线程上引发Elapsed事件。如果Elapsed事件的处理时间长于Interval,则该事件可能会在另一个ThreadPool线程上再次引发。在这种情况下,事件处理程序应该是可重入的。

经过的事件可以发生在Dispose或Stop方法被调用之后,或者在Enabled属性被设置为false之后,因为触发经过的事件的信号总是排队等待线程池线程的执行。解决此竞争条件的一种方法是设置一个标志,告诉Elapsed事件的事件处理程序忽略后续事件。

这只是计时器的设计决策。它有许多可能的解决方案,从并行触发事件、排队处理程序直到前一个处理程序完成,到完全跳过特定的事件。设计师选择了这个选项。他们可以很容易地选择另一个,就像某些其他计时器的设计者所做的那样。

至于为什么不取消,非合作取消代码非常危险,而且非常容易出错,并且tick处理程序的实现通常不会觉得有必要实现合作取消(如果他们真的想的话,他们可以使用现有的实现来实现),所以这不是一个实际的选择。