为什么DateTime.Now和StopWatch会漂移?

kna*_*ten 8 c#

我在C#中创建了一个小型测试应用程序,用于设置DateTime.Now和启动StopWatch.每十秒我打印_stopwatch.Elapsed.TotalMilliseconds(DateTime.Now - _startTime).TotalMilliseconds.

虽然我不认为这两者是完全相同的,但我惊讶地看到它们每20秒线性地发散约1毫秒.我假设DateTime.Now调用系统时钟,而StopWatch做某种积累?

样本输出:

StopWatch : 0,2  DateTime : 1,0 Diff : 0,81
StopWatch : 10000,5  DateTime : 10002,6 Diff : 2,04
(...)
StopWatch : 2231807,5  DateTime : 2231947,7 Diff : 140,13
StopWatch : 2241809,5  DateTime : 2241950,2 Diff : 140,70
Run Code Online (Sandbox Code Playgroud)

完整来源:https://gist.github.com/knatten/86529563122a342de6bb

输出:https://gist.github.com/knatten/84f9be9019ee63119ee2

Gus*_*dor 4

答案相对简单。

  • 秒表使用性能计数器来计算处理器的滴答数,这是一种因处理器而异的机制。
  • DateTime 查询系统时钟 - Windows 使用主板上的(可能是石英)晶体时钟的输出定期更新系统时钟。

所有时钟都会漂移,这两种不同的计时机制将以不同的速率漂移。

在幕后,Stopwatch 使用这个 API

Stopwatch 类有助于在托管代码中操作与计时相关的性能计数器。具体来说,Frequency 字段和 GetTimestamp 方法可用于代替非托管 Win32 API QueryPerformanceFrequency 和 QueryPerformanceCounter。

DateTime 使用这个API

  • 不仅物理时钟会发生漂移,而且 DateTime.(Utc)Now 可能还会重新调整为网络时间源。例如,参见[Hans Passant的回答](http://stackoverflow.com/a/19736972/709537)类似的问题。 (2认同)