【问题标题】:Best way to implement a high resolution DateTime.UtcNow in C#?在 C# 中实现高分辨率 DateTime.UtcNow 的最佳方法是什么?
【发布时间】:2013-11-01 21:27:12
【问题描述】:

我正在尝试实现一个时间服务,它会以超过 1 毫秒的精度报告时间。我认为一个简单的解决方案是进行初始测量并使用 StopWatch 为其添加增量。问题在于,这种方法似乎与挂壁时间的分歧极快。例如,以下代码尝试测量挂钟时间和我的高分辨率时钟之间的差异:

public static void Main(string[] args)
{
    System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();
    DateTime baseDateTime = DateTime.UtcNow;
    s.Start();
    long counter = 0;
    while(true)
    {
        DateTime utcnow = DateTime.UtcNow;
        DateTime hpcutcnow = baseDateTime + s.Elapsed;
        Console.WriteLine(String.Format("{0}) DT:{1} HP:{2} DIFF:{3}", 
            ++counter, utcnow, hpcutcnow, utcnow - hpcutcnow));
        Thread.Sleep(1000);
    }
}

我在最近的服务器硬件上以大约 2 毫秒/分钟的速度发散。

Windows 中是否还有其他我不知道的时间设施会更准确?如果没有,是否有更好的方法来创建我应该使用的高分辨率时钟或第 3 方库?

【问题讨论】:

  • 问题:如果DateTime.UtcNow 对你来说不够准确,那么你会用什么来播种你的时间服务?
  • 除了@Hans 的出色回答之外,我还要补充一点,您可能会尝试使用硬件设备(带有“昂贵的晶体振荡器”的东西)来完成此操作。我不确定您是否可以在 Windows 机器上传输 [并利用] 亚毫秒时间。

标签: c# time stopwatch


【解决方案1】:

获得准确的时钟很困难。秒表具有非常高的分辨率,但它并不准确,它的频率来自芯片组中的信号。它以典型的电子零件公差运行。硬件业务的激烈竞争抢占了价格昂贵且频率有保证且稳定的晶振。

DateTime.UtcNow 也不是那么准确,但它得到了帮助。 Windows 会定期联系时间服务,默认是 time.windows.com 以获得高质量时钟的更新。并使用它来重新校准机器的时钟,插入小的调整以使时钟赶上或放慢速度。

您需要很多更大的技巧才能将其精确到毫秒。对于在内核模式下运行的代码,您只能获得这样的保证,以中断优先级运行,因此它不能被其他代码抢占,并且其代码和数据页被页面锁定,因此它不会受到页面错误的影响.商业解决方案使用 GPS 无线电读取 GPS 卫星的时钟信号,并由在烤箱中运行以提供温度稳定性的振荡器作为支持。读取这样的时钟是一个难题,当您使用亚毫秒时钟源的程序可以在获得时间时被操作系统抢占并且不会再次开始运行时,您没有太多用处约 45 毫秒后。或者更糟。

DateTime.UtcNow 精确到 15.625 毫秒,并且由于时间服务更新而在很长一段时间内保持稳定。低于此值并没有多大意义,您无法在用户模式下获得利用它所需的执行保证。

【讨论】:

    【解决方案2】:

    显然在 Windows 8/Server 2012 中添加了一个新 API,专门用于获取高分辨率时间戳,GetSystemTimePreciseAsFileTime API。我还没有机会玩这个,但它看起来很有希望。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-21
      • 2011-05-24
      • 2014-05-20
      • 1970-01-01
      • 1970-01-01
      • 2010-12-18
      • 1970-01-01
      相关资源
      最近更新 更多