【问题标题】:Why is Thread.Sleep is not precise for long durations?为什么 Thread.Sleep 长时间不精确?
【发布时间】:2011-09-30 06:13:10
【问题描述】:

我有一个用 C# 编写的服务。服务全天候处于活动状态,但一个线程通过 Thread.Sleep 休眠到预定时间 - 通常是晚上 9 点到晚上 11 点 - 以执行一些内务处理任务。首次服务启动时,它以毫秒为单位计算时间跨度,直到管家时间,并使用该时间跨度调用 Thread.Sleep。下次线程只需调用 Thread.Sleep(24*60*60*1000) 来休眠 24 小时。

除了单一安装,它工作得很好,当睡眠提前几分钟 - 根据跟踪日志提前 5-8 分钟唤醒时。在几个星期内,家政时间会改变几个小时。我可以预期,管家时间可以向前移动,而不是向后移动。想知道是否有人可以解释一下。我必须承认,我不是在寻找解决问题的不同解决方案 - 只是试图解释这种行为。

【问题讨论】:

  • 系统时钟本身是否在该机器上漂移?
  • 不要使用睡眠。
  • 也许系统时钟在某处被重置?对于调试,您可以有另一个线程每 10 分钟打印一个日志行
  • 您是否尝试过使用“计划任务”?您可能还想尝试一下taskscheduler.codeplex.com
  • Quartz.NET 在这些情况下是主角

标签: c# multithreading


【解决方案1】:

Thread.Sleep 不是为像您所做的那样长时间准确睡眠而设计的。你应该使用像System.Threading.Timer 这样的东西。你可以给它一个午夜的第一次运行时间,并让它每 24 小时关闭一次。 Timer(TimerCallback, Object, TimeSpan, TimeSpan) 构造函数正是您正在寻找的。​​p>

【讨论】:

  • 睡眠的准确性是否在某处定义?让我担心的是,这种实质性的漂移只发生在一台服务器上。数百台服务器就好了。我担心那台机器上发生的事情可能会影响其他解决方案。但是什么?
【解决方案2】:

Sleep 不使用挂钟来计算时间。为此,它使用大约每 10 毫秒出现一次的定期中断间隔(可调节且取决于操作系统版本)。用于这些中断的时间源是一个廉价的石英,它在历史上被用于一些其他功能,所以它的频率既不完全是 1/10 毫秒,而且在一台机器到另一台机器之间波动。

解决问题的正确方法是缩短睡眠时间并检查是否到了真正醒来的时间。

另外,这里希望当您说您正在使用 Sleep() 时,实际上您正在等待一个超时事件。

【讨论】:

  • 我会说“正确的方法”是使用计时器,但那可能只是我 ;-) 否则 +1。
  • @pst:谢谢 :) 计时器是正确的,但它仅在 .NET 上可用。上面的方法是可移植的,可以在任何平台上工作。实际上,得知这也是 Timer 的实现方式,我不会感到惊讶(我不确定)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-23
  • 1970-01-01
  • 1970-01-01
  • 2012-01-04
  • 2020-03-03
  • 1970-01-01
相关资源
最近更新 更多