0

我制作了一个 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

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

4

2 回答 2

1

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

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

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

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

于 2014-07-01T13:58:41.943 回答
1

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

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

于 2014-07-01T14:03:05.873 回答