我知道DateTime.Now
(或DateTime.UtcNow
)仅对系统计时器分辨率有效。有一个“未记录的”函数NtSetTimerResolution,但doesn't affect the current time。我已经在使用DateTime.UtcNow
的起始值和添加的Stopwatch
计数器的混合解决方案,以获得最高精度到微秒。实际上这很好用,它只是不能与来自系统上多个进程的时间值进行比较。
我想现在进一步校准我的基准时间。如果DateTime.Now
的准确性无法提高,至少我想知道它的值何时更新为下一个值。我想到一个循环旋转很长时间,直到值发生变化,然后使用它并立即启动秒表。
像这样:(未经测试)
DateTime t0 = DateTime.UtcNow;
DateTime baseTime;
Stopwatch stopwatch = new Stopwatch();
while ((baseTime = DateTime.UtcNow) == t0);
stopwatch.Start();
我的假设是否正确,等待改变的价值给了我报告值准确的时刻?例如,如果我在报告给公共日志的所有应用程序中执行此操作,那么我应该获得比现在更具可比性的时间值。 (我不想获得同步级别的准确性,只是更好的信息。)
我已经使用NtSetTimerResolution函数进行了一些测试,将其设置为最大分辨率并在循环中比较DateTime.UtcNow
值。似乎值更精确/准确(这里无法区分)。但我不确定我在这里看到了什么。目前该计划开始时的决议每次都不同。不确定它是否会干扰其他进程,所以我不想在生产代码中修改它。
答案 0 :(得分:0)
NtSetTimerResolution()
会更改系统计时器分辨率。在这个意义上,它似乎与timeBeginPeriod
/ timeEndPeriod
非常相似。但是NtSetTimerResolution可以在支持更高分辨率的硬件上启用低于1 ms的定时器分辨率。使用NtQueryTimerResolution
调查限制。运行Windows XP以上的大多数现代硬件都支持0.5毫秒的分辨率。
这对时间有何影响?好吧,在Windows上> XP系统时间(系统文件时间)的粒度或系统时间的更新间隔由系统心跳确定,系统心跳由定时器分辨率给出。
示例:
1)Windows 7,NtQueryTimerResolution返回的最大分辨率为5000(100 ns单位)。 NtSetTimerResolution允许将系统心跳设置为0.5 ms。系统时间(使用GetSystemTimeAsFileTime获得适当的检测分辨率)将以0.5 ms的步长递增。所以当前时间受到影响,它的粒度会发生变化。
2)Windows> XP,timeBeginPeriod(1)将系统心跳更改为1毫秒,但时间粒度仍然很低。系统时间粒度不依赖于Windows XP上的计时器分辨率。
...函数NtSetTimerResolution但它不会影响当前时间。
确实如此。 MSDN: 调用timeBeginPeriod时请小心,因为频繁的调用会显着影响系统时钟,系统电源使用情况和调度程序。但是,MS无法在此更新文档;使用Windows 8.1计时方案取消了对系统时间的影响。顺便说一句:timeBeginPeriod
和 timeEndPeriod
确实使用NtSetTimerResolution
。
提示:在系统时间转换时调用NtSetTimerResolution,timeBeginPeriod和timeEndPeriod以减少效果。这可以通过在呼叫之前轮询系统时间转换来完成。
...将最高精度的秒表计数器添加到微秒。不幸的是Stopwatch
不考虑系统时间调整。您必须查询实际系统时间调整(GetSystemTimeAdjustment 并将此调用获得的增益应用于秒表频率。
摘要:是否更多 ...精确/准确(此处无法区分)。?它具有更精细的粒度,意味着:精确度和准确度。
注意:如此处所述,有人抱怨在高频心跳下运行系统。微软声称功耗增加了25%。其他关于由于高频心跳导致大量兆瓦丢失的写作。像往常一样,你支付的越多,你获得的就越多。