簡體   English   中英

更精確的 Thread.Sleep

[英]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秒表結合使用(確保IsHighResolutionFrequency適合您的需要)。 啟動計時器和秒表,並在計時器的謹慎滴答上檢查秒表的確切經過時間。

如果您試圖對計算進行速率限制並堅持只使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM