Winservice - Timer:并行执行相同的任务

时间:2014-07-01 13:50:47

标签: c# windows-services system.timers.timer

我做了一个Window-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服务或服务器问题)花费的时间更长,则会启动并执行新的'instance' PerformAction。因此PerformAction相互运行了两次(和parallel)。

这是什么原因?为什么以前的PerformAction没有被取消?方法PerformAction是否正在执行Async

我找到了一种解决方法,但我只是不理解这种行为......

2 个答案:

答案 0 :(得分:1)

在您执行操作之前停止计时器然后在执行操作后再次启动计时器

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

System.Timers

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事件的信号始终排队等待在线程池线程上执行。解决此竞争条件的一种方法是设置一个标志,告诉事件处理程序Elapsed事件忽略后续事件。

答案 1 :(得分:1)

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

至于为什么它没有被取消,非合作取消代码非常危险并且极易出错,并且滴答处理程序的实现通常不会感到需要实现合作取消(他们可以使用现有的实现,如果他们真的想要的话),所以这不是一个真正的选择。