[英]More precise Thread.Sleep
我該怎么做 Thread.Sleep(10.4166667);?
好的,我現在知道睡眠不是要走的路。 所以我使用計時器,但計時器也是毫秒,我需要更精確的計時器是否有納秒精度的計時器?
所以你想讓你的線程正好在那段時間休眠然后恢復? 忘記它。 此參數告訴系統至少在此毫秒數后喚醒線程。 至少。 恢復后,線程可以在眨眼間再次進入睡眠狀態。 這就是操作系統的工作方式,您無法控制它。
請注意,只要您告訴Thread.Sleep
休眠(甚至不准確),無論代碼在執行之前或之后需要多長時間。
您的問題似乎暗示您希望在某些時間間隔內執行某些代碼,因為精確的時間似乎很重要。 因此,您可能更喜歡Timer
。
要進行如此精確的睡眠,您需要使用實時操作系統,並且可能需要專門的硬件。 Integrity RTOS 聲稱可以在納秒內響應中斷,其他人也是如此。
這不會發生在 C# 或任何類型的高級睡眠調用中。
請注意,參數以毫秒為單位,因此 10 是 10 毫秒。 您確定要 10.41 等毫秒嗎? 如果你想要 10.41 秒,那么你可以使用 10416。
Thread.Sleep
的輸入是線程被阻塞的毫秒數。 之后它將是可運行的,但您對實際調度的時間沒有影響。 即理論上線程在恢復執行之前可以永遠等待。
在這里依賴特定的毫秒數幾乎沒有任何意義。 如果您嘗試在兩個線程之間同步工作,則有比使用 Sleep 更好的選擇。
正如您已經提到的:您可以將DispatcherTimer與秒表結合使用(確保IsHighResolution
和Frequency
適合您的需要)。 啟動計時器和秒表,並在計時器的謹慎滴答上檢查秒表的確切經過時間。
如果您試圖對計算進行速率限制並堅持只使用Thread.Sleep
那么請注意存在一個底層內核脈沖速率(大約 15 毫秒),因此您的線程只會在脈沖發生時恢復。 提供的保證是“至少等待指定的持續時間”。 例如,如果您調用Thread.Sleep(1)
(等待Thread.Sleep(1)
毫秒),並且最后一個脈沖是 13 毫秒前,那么您將最終等待 2 毫秒,直到下一個脈沖到來。
我為渲染引擎實現的繪制同步執行類似於抖動的操作,以將量化到 15 毫秒間隔均勻分布在我想要的時間間隔內。 這主要是從睡眠持續時間中減去一半的脈沖間隔,因此只有一半的調用等待下一個 15ms 脈沖的額外持續時間,而一半會提前發生。
public class TimeSynchronizer {
//see https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep
public const double THREAD_PULSE_MS = 15.6d;//TODO read exact value for your system
public readonly TimeSpan Min = TimeSpan.Zero;
public TimeSynchronizer(TimeSpan? min = null) {
if (min.HasValue && min.Value.Ticks > 0L) this.Min = min.Value;
}
private DateTime _targetTimeUtc = DateTime.UtcNow;//you may wish to defer this initialization so the first Synchronize() call assuredly doesn't wait
public void Synchronize() {
if (this.Min.Ticks > 0L) {
DateTime nowUtc = DateTime.UtcNow;
TimeSpan waitDuration = this._targetTimeUtc - nowUtc;
//store the exact desired return time for the next inerval
if (waitDuration.Ticks > 0L)
this._targetTimeUtc += this.Min;
else this._targetTimeUtc = nowUtc + this.Min;//missed it (this does not preserve absolute synchronization and can de-phase from metered interval times)
if (waitDuration.TotalMilliseconds > THREAD_PULSE_MS/2d)
Thread.Sleep(waitDuration.Subtract(TimeSpan.FromMilliseconds(THREAD_PULSE_MS/2d)));
}
}
}
如果您的標稱睡眠持續時間明顯小於脈搏率,我不推薦此解決方案,因為在這種情況下它通常不會等待。
以下屏幕截圖顯示了實際需要多長時間的粗略百分比帶(每個桶有 20 個樣本 - 深綠色是中值),幀之間的(標稱)最小持續時間設置為 30fps(33.333ms):
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.