定时器比间隔多10 ms

我正在使用间隔1秒的计时器。 但是在计时器的刻度事件中,当我打印时间时,它总是62或65毫秒。 我不明白为什么它要多花10毫秒。

有人可以看看这个。

这是我正在使用的代码:

static int _counter; var _timer = new System.Timers.Timer(1000); public Form1() { InitializeComponent(); _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed); _timer.Start(); } private void _timer_Elapsed(object sender, ElapsedEventArgs e) { Console.WriteLine(DateTime.Now.ToString("{hh:mm:ss.fff}")); _counter++; if (_counter == 20) _timer.Stop(); } 

这个输出:

 {01:59:08.381} {01:59:09.393} {01:59:10.407} {01:59:11.421} {01:59:12.435} {01:59:13.449} {01:59:14.463} {01:59:15.477} {01:59:16.491} {01:59:17.505} {01:59:18.519} {01:59:19.533} {01:59:20.547} {01:59:21.561} {01:59:22.575} {01:59:23.589} {01:59:24.603} {01:59:25.615} {01:59:26.629} {01:59:27.643} 

您需要了解Windows不是实时操作系统。 实时操作系统具有计时器机制,允许系统对计时器启动的事件何时发生以及与之相关的开销做出硬性保证,并允许您指定在错过最后期限时应发生的行为 – 例如,如果以前的执行时间比间隔长。

在较小的时间间隔内,我会将Windows计时器描述为“尽力而为”。 当间隔足够长时,您没有注意到您没有得到您请求的确切间隔。 随着您越来越接近计时器的分辨率(计时器运行的频率),您开始将间接开头视为间隔增加的百分比。 实时系统需要特别注意最小化软件开销,依赖于更复杂和更快速的硬件解决方案。 Windows计时器的确切频率取决于底层硬件提供的计时服务,因此可能因系统而异。

如果您有实时需求 – 并且每50毫秒做一些事情可能属于该类别 – 那么您可能需要查看专用硬件和/或实时操作系统。

这是因为系统时钟的分辨率有限。 事件发生在指定时间之后的下一个系统节拍中,因此您将总是获得额外的几毫秒。

首先,正如其他人所说,你将它设置为1秒,而不是50毫秒。

其次,Windows不是实时操作系统。 没有一个计时器类是完全精确的。 所有你这样做,说你想等至少这么久。 一切都需要花费一些时间才能解决,并且一旦窗口到达实际服务于滴答消息,您最终会通知计时器已经勾选。

如果你需要一个更精确的计时器,你可以挂钩到Win32多媒体计时器,它是最准确的计时器(低至1毫秒)。 这是一篇关于CodeProject的文章,展示了如何从C#挂钩。

请注意,通常,在大多数语言中,睡眠调用指定进程唤醒之前的最短时间。 在指定的时间过去之后,进程将被放入队列,并希望调度程序激活它。 但这种激活有时可能会延迟。 我不确定Timer类,但我怀疑它可能会遇到类似的问题。
您可能尝试提高流程的优先级以减少增加的时间。

使用系统计时器总是比请求的值稍长。 这是由于系统中其他进程的开销。

System.Timers.Timer不是精确的计时器。 特别是当系统负载不足时,它可能会有更大的延迟。

还要在示例中更准确地更改时间测量代码以使用秒表类。

 static int _counter; System.Timers.Timer _timer = new System.Timers.Timer(1000); Stopwatch sw; public Form1() { InitializeComponent(); _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed); _timer.Start(); sw = Stopwatch.StartNew(); } void _timer_Elapsed(object sender, ElapsedEventArgs e) { Console.WriteLine(sw.ElapsedMilliseconds); _counter++; if (_counter == 20) _timer.Stop(); sw.Reset(); sw.Start(); } 

在我的系统上它是14ms。 用谷歌搜索; 区别在于上下文线程切换延迟。 这里有一篇关于高分辨率计时器的文章

正如其他响应者所提到的,Windows不是实时操作系统。 如果必须使用Windows,请尝试使用Win CE或Windows Embedded。

-S!

时间的准确性可能取决于运行的进程数。 如果你有这个选项,我会逐个减少你的计算机上运行的进程数,我的意思是那些消耗大量cpu时间的进程,我会检查时间是否有所改善。 特别是浏览器,病毒扫描程序,在后台运行的程序。

偏差是正常的,因为它们不是RTOS (实时操作系统)。 这是我在这种情况下找到的最佳解决方案: 链接

 Program.MicroTimer microTimer = new Program.MicroTimer(); microTimer.MicroTimerElapsed += new Program.MicroTimer.MicroTimerElapsedEventHandler(OnTimedEvent); microTimer.Interval = 1000; // Call micro timer every 1000µs (1ms) // Can choose to ignore event if late by Xµs (by default will try to catch up) // microTimer.IgnoreEventIfLateBy = 500; // 500µs (0.5ms) microTimer.Enabled = true; // Start timer System.Threading.Thread.Sleep(2000); microTimer.Enabled = false; 

这些是代码片段。 您可以尝试在控制台中查看值。