Timers.Timer停止触发已发生的事件和!线程显示1023个未启动和未决的线程

时间:2014-11-06 04:14:56

标签: c# .net multithreading timer

我的应用程序在this问题中有一个Timers.Timer实现,似乎在一段时间(几天或几周)之后停止触发它已经过去的事件[经过的事件应该每隔60秒运行一次{{3详情]

0:000> !threads -live
ThreadCount:      1041
UnstartedThread:  1023
BackgroundThread: 11
PendingThread:    1023
DeadThread:       3
Hosted Runtime:   no

稍后,我们发现当已发生的事件停止被触发时,unstartedpending个线程的数量也会持续增加,直到达到1023限制。然后这个过程陷入困境。

我的Timer没有触发事件和#threads(未启动和未决)的最终上升之间的原因/原因或关系是什么?

perf logs showing the rise in thread count when the timer stopped firing the elapsed event

2 个答案:

答案 0 :(得分:2)

几乎可以肯定你的计时器事件处理程序没有退出。无论是阻塞(在Sleep中还是等待某个事件),或者它已进入无限循环。然后下一个计时器事件出现, it 阻塞或进入无限循环。等等。 。

您可以通过更改计时器事件处理程序来确定是否是这种情况,以便它告诉您是否重新输入:

private bool _inTimer = false;
private void TimerTick(object Sender, ElapsedEventArgs e)
{
    if (_inTimer)
    {
        // there's already a timer running.
        // log a message or notify you in some other way.
    }
    _inTimer = true;
    // do your processing here
    // and then clear the flag
    _inTimer = false;
}

那将告诉你我怀疑是否是这种情况。但是,不要将它用作防止并发计时器实例的生产方式。有一个Boolean标志的竞争条件。如果要防止并发计时器滴答,请在输入方法时禁用计时器,然后在退出时重新启用它。像这样:

private void TimerTick(object Sender, ElapsedEventArgs e)
{
    _myTimer.Enabled = false;
    // do processing
    // then re-enable the timer
    _myTimer.Enabled = true;
}

在相关的说明中,另一个可能导致计时器似乎停止运行的事情是它抛出了一个异常,运行时库在没有浮出水面的情况下压扁。这种行为是documented

  

Timer组件捕获并抑制事件处理程序为Elapsed事件抛出的所有异常。在将来的.NET Framework版本中,此行为可能会发生更改。

因此,如果您的事件处理程序中的异常未被捕获,则会将其丢弃。出于这个原因,我建议不要使用System.Timers.Timer。我建议改用S ystem.Threading.Timer,因为它没有遭受这种愚蠢的设计。

答案 1 :(得分:0)

我最终修改/修改了Timer实现,并使用带有do-while循环的Thread。这样可以避免“未知”。我们从定时器过去的事件中得到的问题没有解决。

全部谢谢