.NET 秒錶類可以這麼可怕嗎?
我正在製作一個需要非常緊迫的時間的應用程序,而 Stopwatch 類是完美的解決方案。但是,我有時注意到,在小型平板電腦上執行時,秒錶值會偏離。我添加了一些調試列印輸出,每 200 毫秒左右監控一次秒錶的值:
0:00:197
0:00:502
0:00:702
…
**0:03:356
0:12:93**
0:13:21
0:13:421
…
它怎麼可能從約 3 秒跳到約 13 秒?我現在看到底層函式 QueryPerformanceCounter() 是錯誤*的(當心 QueryPerformanceCounter()*),但我感覺到這裡正在發生其他事情。
任何見解都值得讚賞。
更新:
這是我的程式碼的更多細節:它非常簡單。這是一個 WPF 應用程序,它在啟動時創建一個新
Stopwatch對象,然後通過Start(). 然後我創建一個DispatcherTimer,像這樣:displayTimer = new DispatcherTimer(); displayTimer.Tick += display_Tick; displayTimer.Interval = DISPLAY_INTERVAL_TIMESPAN;其中時間跨度為 200 ms。
Stopwatch我的調試程式碼只是在每次dispatchTimer滴答聲時列印出對象的值。更新2:
一篇有趣的 Microsoft 支持文章是*性能計數器值可能會意外飛躍*。
更新(查看您的日誌後)
正如您已經提到的,
Stopwatch該類使用QueryPerformanceCounter下面的函式。在備註部分 MSDN 說:在多處理器電腦上,呼叫哪個處理器並不重要。但是,由於基本輸入/輸出系統 (BIOS) 或硬體抽象層 (HAL) 中的錯誤***,您可能會在不同的處理器上獲得不同的結果。***要指定執行緒的處理器親和性,請使用 SetThreadAffinityMask 函式。
當您使用 Dispatcher時,
QueryPerformanceCounter每次查詢經過的時間時,可能不會在同一個 CPU 上執行。您可以通過為您的程序指定處理器親和性來檢查 MSDN 中提到的問題是否是您的問題的原因,例如通過使用
start命令呼叫您的執行檔。對我來說,CPU 之間的 10 秒似乎是一個很大的延遲,但是文件對於差異可能有多大非常模糊。以下命令會將您的應用程序綁定到第一個 CPU:> start.exe /AFFINITY 1 program.exe如果這應該解決問題,您可能需要查看建議的解決方法,即
SetThreadAffinityMask在查詢Stopwatch對象之前呼叫該函式。
您的評論說您正在使用 WPFDispatcherTimer。該類的文件指出:定時器不能保證在時間間隔發生時準確執行,但可以保證在時間間隔發生之前不會執行。這是因為 DispatcherTimer 操作像其他操作一樣放置在 Dispatcher 隊列中。DispatcherTimer 操作何時執行取決於隊列中的其他作業及其優先級。
這意味著計時器事件可能會延遲到達,尤其是在調度程序忙於其他任務時。您是否在調度程序隊列中放置了其他會阻止事件更早觸發的東西?