2010-03-12 42 views
10

从Windows服务使用System.Threading.Timer(.NET 2.0)时,我们遇到了以下问题。C#计时器在间隔时间之前被解雇

  1. 大约有12个不同的计时器对象.
  2. 每个计时器都有到期时间和间隔。这是正确设置的。
  3. 观察到在3到4小时后,定时器在它们的间隔过去之前开始发信号。例如,如果计时器应该在4:59:59发出信号,则会在7秒前的4:59:52发出信号。

有人能告诉我这种行为的原因是什么,解决方法是什么?

谢谢, Swati

回答

0

也许再调度,需要一些秒即可完成操作后进行。或者你不控制这个?

0

这不可能控制,因为它依赖于系统的速度,如果你有超级计算机则有可能是没有足够的差异,但如果你有正常的PC然后就会出现后不久在定时间隔差执行。

希望这会有所帮助。

9

大问题...和这里的原因:

“时序”是一件棘手的事情,当它涉及到计算机......你可以永远依靠“间隔”是完美的。有些计算机会每隔14到15毫秒就会对计时器进行“打勾”,其中一些频率比较频繁,一些频率较低。

所以:

Thread.Sleep(1); 

可能从1到30毫秒的任何地方运行。相反,如果您需要更精确的计时器 - 您必须捕获开始时的DateTime,然后在计时器中,您必须通过减去DateTime.Now和原始时间来检查它是否为“时间来运行“你的代码。

下面是你需要做的一些示例代码:

DateTime startDate = DateTime.Now; 

然后,设置为1毫秒的间隔启动定时器。然后,在你的方法中:

if (DateTime.Now.Subtract(startDate).TotalSeconds % 3 == 0) 
{ 
    // This code will fire every 3 seconds. 
} 

上面的代码将每3秒忠实地触发一次。你可以让它运行10年,并且它每3秒钟仍然会启动。

+0

我知道这只是一个例子,但是你不会将计时器间隔增加到100甚至500毫秒之类吗?我知道你可能会失去一点准确性,但是当你每3秒钟只需要一个结果时,这不会比每秒钟发射1000次定时器更好吗? – 2010-03-12 14:12:43

6

蒂莫西的解释很有说服力,但System.Threading.Timer已经以这种方式工作。至少在Rotor实现中,它使用GetTickCount()返回的值来计算下一次回调到期的时间。真正的CLR不太可能这样做,它更可能使用CreateTimerQueueTimer()。不过,这个API函数也可能依赖于由时钟滴答中断递增的内部滴答。

争议的焦点是内部时钟如何剔(通过的GetTickCount()和环境返回。TickCount)与绝对挂钟时间保持同步(由DateTime.Now返回)。不幸的是,这是您机器上的HAL实现细节,即硬件抽象层。机器制造商可以提供定制的HAL,这是一种可以与机器的BIOS和芯片组协同工作的定制HAL。

如果机器有两个定时源,一个时钟芯片被设计用来跟踪挂墙时间并且即使拔下机器电源也能保持滴答状态,另一个频率可以分配到芯片组上提供时钟中断。原来的IBM AT PC以这种方式工作。时钟芯片通常可以被信任,如果时钟不准确,时钟将被关闭。芯片组不能,削减振荡器的质量是一个简单的方法来节省一分钱。

解决您的问题,避免您的计时器长时间,并从回调中的DateTime.Now重新计算下一个到期时间。

+0

感谢您的帮助。重新计算定时器可能会解决我的问题。我要去尝试一下。再次感谢 !! – 2010-03-15 07:09:31