2014-04-30 44 views
8

我在C#中做了一個小測試應用程序,它設置DateTime.Now並啓動一個StopWatch。每十秒打印一次_stopwatch.Elapsed.TotalMilliseconds(DateTime.Now - _startTime).TotalMilliseconds爲什麼DateTime.Now和StopWatch漂移?

雖然我不認爲兩者是相同的,但我驚訝地發現它們每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 

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

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

+0

想想看......你不能在完全相同的時間打電話給他們都在同一行...所以,是的,你的計時器內,所花費的時間打印日期時間的信息,然後THEN打印秒錶的信息,無論他們是多麼接近他們(一個接一個地),超過20秒,將顯示相對較小的差異(1毫秒)... – MaxOvrdrv

+4

@MaxOvrdrv雖然這可能會帳戶對於最初的差異,它不會導致OP中規定的一致漂移。 – Ashigore

+1

@Ashigore你是對的......它應該是在所有打印輸出中看到的差異......我不知道......也許他的內部時鐘電池電量不足? ;) – MaxOvrdrv

回答

3

答案是比較直接的。

  • 秒錶使用性能計數器計數處理器滴答聲,處理器之間的機制會有所不同。
  • DateTime查詢系統時鐘 - 系統時鐘通過使用主板上(可能是石英)水晶時鐘輸出的窗口定期更新。

所有時鐘漂移,這兩種不同的時序機制將以不同的速率漂移。

引擎蓋下,Stopwatchuses this API

秒錶類協助的託管代碼內定時相關 性能計數器的操縱。具體而言,頻率 字段和GetTimestamp方法可用於替代Win32 API的非託管 QueryPerformanceFrequency和QueryPerformanceCounter。

DateTimeuses this API

+2

不僅物理時鐘漂移,而且日期時間(Utc)現在還可以重新調整到網絡時間源。見例如[Hans Passant的回答](http://stackoverflow.com/a/19736972/709537)到一個類似的問題。 –

3

DateTime.Now蜱每隔幾毫秒。而且,機器間的差異並不是固定的。在現代windows系統機器上,你可以預計tick分辨率將在每秒100滴左右。

另一方面,StopWatch查詢CPU硬件以獲得高精度。其實你可以使用Stopwatch.Frequency得到StopWatch的分辨率。

我不知道以上兩種情況,直到我讀到Eric Lippert的一篇有趣的帖子,關於常見性能基準測試錯誤,請看這裏here。這真的是一個偉大的職位。

+0

通過打勾,你的意思是DateTime.Now滴答並積累?我希望它能查詢系統時鐘。 – knatten

+0

據我所知,DateTime.Now和StopWatch都有不同的利率。 – Christos

+0

他們以不同的速率打勾,但似乎秒錶會累積滴答,而DateTime會重新查詢系統時間,請參閱Gusdor的答案。 – knatten

2

StopwatchDateTime更精確這將該差異

MSDN

通過計數定時器在底層定時器機制蜱經過時間秒錶措施。如果安裝的硬件和操作系統支持高分辨率性能計數器,則秒錶類會使用該計數器來測量已用時間。否則,秒錶類會使用系統計時器來測量已用時間。使用Frequency和IsHighResolution字段來確定秒錶計時實施的精度和分辨率。

+0

秒錶更精確,但哪一個更準確?他們是否都累積滴答,還是DateTime.Now查詢系統時鐘?在這種情況下,我們可能會有更精確的秒錶,但更準確的日期時間。 – knatten

+1

準確性會因硬件配置而異。 – Gusdor