我的应用程序有一个 Timers.Timer 实现,如 this 所示一段时间(几天或几周)后似乎停止触发其已用事件的问题[已用事件应该每 60 秒运行一次,请参阅 this详情]
0:000> !threads -live
ThreadCount: 1041
UnstartedThread: 1023
BackgroundThread: 11
PendingThread: 1023
DeadThread: 3
Hosted Runtime: no
后来,我们发现,当 elapsed 事件停止触发时,未启动
和 pending
线程的数量也会持续增加,直到 1023
已达到限制。然后这个过程就卡住了。
我的计时器未触发事件与 # 个线程(未启动和待处理)的最终上升之间的原因/原因或关系是什么?
最佳答案
几乎可以肯定,您的计时器事件处理程序没有退出。它要么阻塞(处于 sleep 状态或等待某个事件),要么进入无限循环。然后下一个计时器事件出现,它要么阻塞,要么进入无限循环。 ETC 。 。 .
您可以通过更改计时器事件处理程序来确定是否是这种情况,以便它告诉您是否重新输入:
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 :
The Timer component catches and suppresses all exceptions thrown by event handlers for the Elapsed event. This behavior is subject to change in future releases of the .NET Framework.
因此,如果异常在事件处理程序中未被捕获,它就会被丢弃在地板上。正是由于这个原因,我建议不要使用 System.Timers.Timer。我建议使用 S ystem.Threading.Timer相反,因为它不会遭受这种愚蠢的设计。
关于c# - Timers.Timer 停止触发已用事件并且 !Threads 显示 1023 个未启动和挂起的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26771607/