【问题标题】:Timer more reliable than System.Threading.TimerTimer 比 System.Threading.Timer 更可靠
【发布时间】:2012-05-28 08:53:38
【问题描述】:

我目前以 10 秒的间隔使用 System.Threading.Timer。每次定时器触发时,我都会添加一小段代码写入文件,虽然大多数时候它会按时触发,但有时(大概是在购买应用程序的其余部分时)无法触发 30或 40 秒,然后快速连续地反复开火。

我可以在 .NET 3.5 中使用更可靠的计时器吗?

定时器设置如下

Timer someTimer = new Timer(new TimerCallback(SomeMethod), null, 0, 10000);

...回调是:

private static void SomeMethod(object state)

但是,很难提供比这更多的代码,因为计时器通常会正确触发。当它嵌入到一个大型应用程序中(大约 100,000 行左右),多个线程被触发时,左、右和中心,你慢慢开始看到计时器间歇性地触发。 我看过几篇帖子暗示线程池可能已用尽,所以我目前正在查看这是否可能是我正在经历的。

【问题讨论】:

  • 您能否提供一些示例代码,而不是假设计时器不可靠?我倾向于发现问题出在我自己的代码上,而不是 .NET 框架。
  • 定时器设置如下:
  • 线程池饥饿很可能是如果处理滴答的时间超过 10 秒。你会慢慢得到积压的物品。标准策略是在进入滴答事件时停止计时器并在结束时重新启动它,以免由于处理时间长而出现“计时器泄漏”。
  • 您是否在应用程序的任何地方使用了Parallel.ForEachParallel.For 循环?如果这样做,请确保将MaxDegreeOfParallelism 配置为合理的值(如Environment.ProcessorCount)。否则,您将获得无限并行的效果(默认配置),这意味着 ThreadPool 将饱和,直到源可枚举完成。

标签: c# .net timer


【解决方案1】:

在 .net 中引用不同的计时器类

.NET 中有三个称为“Timer”的计时器类。听起来您使用的是 Windows 窗体,但实际上您可能会发现 System.Threading.Timer 类更有用 - 但要小心,因为它会回调池线程,因此您无法直接与窗体交互回调。

更准确的计时器 - 根据 MSDN

Windows 窗体计时器组件是单线程的,精度限制为 55 毫秒。如果您需要更准确的多线程计时器,请使用 System.Timers 命名空间中的 Timer 类。

【讨论】:

  • 听起来他可能正在使用它,但他实际上说他正在使用System.Threading.Timer,根据节拍器的质量,这是两个最“可靠”的选择之一。
  • 嗨,Romil,谢谢,正如其他人指出的那样,这似乎是线程池饥饿问题,但仍然感谢表。我相信它迟早会派上用场。
  • 其实System.Timers Timer不是线程安全的:"任何实例成员都不能保证是线程安全的。",而System.Threading.Timer是:"这种类型是线程安全的。”
【解决方案2】:

这听起来很像线程池饥饿。寻找在线程池中运行的长时间运行/阻塞作业,或者使用异步 io 重写,或者在长时间运行 CPU 密集型作业的情况下,根本不要在线程池中运行这些作业。在自己的线程上运行它们或使用后台工作者。

【讨论】:

  • 我希望它可能只是 System.Threading.Timer 特有的问题,并且通过切换到另一个 Timer,我能够解决这个问题。在你的提示和仔细检查之后,它确实看起来像一个 ThreadPool 饥饿问题。谢谢大家的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-28
  • 2017-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多