我的应用程序在this问题中有一个Timers.Timer实现,似乎在一段时间(几天或几周)之后停止触发它已经过去的事件[经过的事件应该每隔60秒运行一次{{3详情]
0:000> !threads -live
ThreadCount: 1041
UnstartedThread: 1023
BackgroundThread: 11
PendingThread: 1023
DeadThread: 3
Hosted Runtime: no
稍后,我们发现当已发生的事件停止被触发时,unstarted
和pending
个线程的数量也会持续增加,直到达到1023
限制。然后这个过程陷入困境。
我的Timer没有触发事件和#threads(未启动和未决)的最终上升之间的原因/原因或关系是什么?
答案 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。这样可以避免“未知”。我们从定时器过去的事件中得到的问题没有解决。
全部谢谢