【问题标题】:Accurate Windows timer? System.Timers.Timer() is limited to 15 msec准确的 Windows 计时器? System.Timers.Timer() 限制为 15 毫秒
【发布时间】:2014-04-06 02:42:18
【问题描述】:

我需要一个准确的计时器来将 Windows 应用程序连接到一台实验室设备。

我使用 System.Timers.Timer() 创建了一个每 10 毫秒计时一次的计时器,但是这个时钟运行缓慢。例如,间隔为 10 毫秒的 1000 个滴答应该需要 10 挂钟秒,但实际上需要 20 挂钟秒(在我的 PC 上)。我猜这是因为 System.Timers.Timer() 是一个间隔计时器,每次经过时都会重置。由于在计时器经过和重置(再过 10 毫秒)之间总是需要一些时间,因此时钟运行缓慢。如果间隔很大(秒或分钟),这可能很好,但对于非常短的间隔是不可接受的。

Windows 上是否有一个函数会在系统时钟每次超过 10 毫秒(或其他)边界时触发一个过程?

这是一个简单的控制台应用程序。

谢谢

标准

更新:System.Timers.Timer() 对于小间隔非常不准确。

我写了一个简单的程序,用几种方法计算 10 秒:

间隔=1,计数=10000,运行时间=160 秒,每间隔毫秒=16

间隔 = 10,计数 = 1000,运行时间 = 16 秒,每间隔毫秒 = 15

间隔 = 100,计数 = 100,运行时间 = 11 秒,每间隔毫秒 = 110

间隔 = 1000,计数 = 10,运行时间 = 10 秒,每间隔毫秒 = 1000

似乎 System.Timers.Timer() 的滴答速度不能超过 15 毫秒,不管怎样 间隔设置。

请注意,这些测试似乎都没有使用任何可测量的 CPU 时间,因此限制不是 CPU,只是 .net 限制(错误?)

现在我认为我可以忍受每 15 毫秒左右触发一个例程的不准确计时器,并且该例程获得准确的系统时间。有点奇怪,但是...

我还发现了一个共享软件产品 ZylTimer.NET,它声称是一个更准确的 .net 计时器(分辨率为 1-2 毫秒)。这可能是我需要的。如果有一种产品,那么很可能还有其他产品。

再次感谢。

【问题讨论】:

  • 您应该说明您的实际规格,您需要的最小刻度间隔是多少,公差是多少?

标签: vb.net


【解决方案1】:

您需要使用high resolution timer,例如QueryPerformanceCounter

【讨论】:

  • MSDN 上也有一篇不错的文章:Implement a Continuously Updating, High-Resolution Time Provider for Windows (msdn.microsoft.com/en-us/magazine/cc163996.aspx)
  • 从 .NET 2.0 开始,高分辨率秒表已经可用(假设操作系统支持它)。但是,在这种情况下,这并不是那么有用。第二个可能是。
  • @Patrick:您的链接可能指向正确的方向,也许答案就在那里,在这种情况下,它需要作为答案包含在内。
  • @Patrick,很抱歉,您的链接已过期。 MSDN 说“此内容已停用。”
【解决方案2】:

从表面上看,答案类似于“高分辨率计时器”,但这是不正确的。答案需要定期生成刻度,而 Windows 高分辨率性能计数器 API 不会生成这样的刻度。

我知道这不是自己的答案,但到目前为止对这个问题的流行回答是错误的,足以让我觉得对它的简单评论是不够的。

【讨论】:

  • “常规的tick生成”是什么意思?
  • @Ahmed:创建某种具有周期性间隔的事件,即时钟信号。问题是要求准确传递此类事件。这里的最佳答案是错误的,不可能在 Windows 等非确定性操作系统中提供这样的东西。
【解决方案3】:

限制是由系统心跳给出的。这通常默认为 64 拍/秒,即 15.625 毫秒。但是,有一些方法可以修改这些系统范围的设置,以在较新的平台上实现低至 1 毫秒甚至 0.5 毫秒的计时器分辨率:

  1. 通过多媒体计时器接口 (timeBeginPeriod()) 实现 1 毫秒分辨率:

    Obtaining and Setting Timer Resolution

  2. 通过NtSetTimerResolution() 达到 0.5 毫秒分辨率:

    Inside Windows NT High Resolution Timers

可以通过隐藏 API NtSetTimerResolution() 获得 0.5 毫秒的分辨率。

我已经在this SO answer中提供了所有详细信息。

【讨论】:

    【解决方案4】:

    在 System.Diagnostics 中,您可以使用 Stopwatch 类。

    【讨论】:

      【解决方案5】:

      在我的脑海中,我可以建议运行一个大部分时间都在休眠的线程,但是当它醒来时,它会检查正在运行的 QueryPerformanceCounter 并偶尔会触发您的过程。

      【讨论】:

      • 再次确定性是这里的一个因素,这个问题确实需要一个明确的周期和容差规范,以便能够确定这个解决方案是否可行。
      【解决方案6】:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-10
        相关资源
        最近更新 更多