在 Windows 上,Environment.TickCount 及 Environment.TickCount64 已經更新,以符合作業系統底層等待 API 的行為。 他們不再將睡眠或冬眠時間納入經過時間的計算範圍。 此變更也使 Windows 行為與其他平台一致,並確保更新頻率與系統底層中斷計時器相同。 此變更允許選擇較高頻率更新的應用程式提升反應速度。
推出的版本
.NET 11 預覽版 1
先前的行為
先前在 Windows 上,會 Environment.TickCount64 回傳 Win32 GetTickCount64 API 的結果,該 API 以固定的頻率更新 10-16 毫秒(通常為 15.5 毫秒),並包含系統在睡眠、休眠或其他低功耗狀態中所花費的時間。
在其他平台(如 Linux 和 macOS)上,更新 Environment.TickCount64 頻率與系統底層中斷計時器相同,且只包含系統被視為「醒著」的時間。
在所有平台上,Environment.TickCount 返回了 Environment.TickCount64 的截斷結果,並且展現出完全相同的行為,但大約每49天會發生一次溢出。
新行為
在 Windows 上,現在會 Environment.TickCount64 回傳 Win32 QueryUnbiasedInterruptTime API 的結果。 此變更使 .NET API 與作業系統底層等待 API 的行為保持一致。 它不再包含非喚醒時間,且更新頻率與系統底層中斷計時器相同。
在其他平台上, Environment.TickCount64 仍維持其行為,這與 Windows 的新行為一致。
在所有平台上,Environment.TickCount 維持其實作,並鏡射 Environment.TickCount64 的行為。
破壞性變更的類型
此變更為行為變更。
變更的原因
Windows 在 Windows 8、Windows Server 2012 及更新版本中也採取了類似的行為破壞性變更,導致接受逾時的 API(如 SleepEx 和 WaitForMultipleObjectsEx)不再考慮非醒著時間。 這導致與 .NET 不一致,因為此類等待 API 經常與 Environment.TickCount64 一起使用,進而導致難以診斷的錯誤,例如計時器意外觸發。
此外,所使用的底層 API GetTickCount64 精度較低,且僅以固定解析度更新。 若作業系統的底層中斷計時器頻率改變,該解析度並未被調整,這可能導致選擇以較高優先權執行的應用程式需要額外工作。 這種行為也與其他平台如 macOS 和 Linux 的行為不一致。
此變更確保與底層作業系統及跨平台的一致性。 同時也可能導致選擇更頻繁更新的應用程式反應速度提升。
建議的動作
除非選擇使用較高頻率的中斷時間,否則大多數程式碼不應該會有行為改變。 應用程式更新頻率將與以往保持不變。 不過,如果更新頻率是相關的,請確保逾時時間傳遞的值正確且符合程式碼的期望,或確保應用程式不會選擇過高的更新頻率。 (這目前只能透過 P/Invoke API 實現。)
有些程式碼可能會出現計時器在機器從休眠或低功耗狀態喚醒後不會立即觸發的情況。 若時間相關,請使用API DateTime.UtcNow ,確保該時間可隨時包含。 這類程式碼可能必須考慮可能的時鐘調整。
受此變更影響的 Windows 程式碼,很可能已經在其他平台如 Linux 和 macOS 上遭遇同樣情況。