c# - Timers.Timer 停止触发已用事件并且 !Threads 显示 1023 个未启动和挂起的线程

标签 c# .net multithreading timer

我的应用程序有一个 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 已达到限制。然后这个过程就卡住了。

我的计时器未触发事件与 # 个线程(未启动和待处理)的最终上升之间的原因/原因或关系是什么?

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

最佳答案

几乎可以肯定,您的计时器事件处理程序没有退出。它要么阻塞(处于 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/

相关文章:

c# - 使用 if/then/else 来翻转 boolean 值或否定是否更好?

c# - 如何在 C# 中从维基百科的页面中提取维基代码而不是 html?

c# - 正确打印二维数组?

.Net 用户范围应用程序设置文件路径问题

multithreading - C++ std::mutex和Windows CreateMutex有什么区别

c# - C#异步套接字概念

.net - 从坐标保存 map 图像

.net - 在 .Net 应用程序中管理来自单个 Socket 的并发读取

java - 有没有比使用 CountDownLatch 更好的等待两个线程完成任务的方法?

java - 如何在 Java 中同步运行一个进程?