簡體   English   中英

Thread.Sleep 或 Thread.Yield

[英]Thread.Sleep or Thread.Yield

我有一種方法,它使用后台工作人員輪詢 DLL 以獲取如下所示的狀態:

var timeout = DateTime.Now.AddSeconds(3);
while (System.Status != Status.Complete  // our status is not complete
       && DateTime.Now < timeout         // have not timed out
       && !_Worker.CancellationPending)  // backgroundworker has not been canceled
{
    //Thread.Yield();
    //Thread.SpinWait(1);
    //Thread.Sleep(1);
}

查看我的 CPU % 時, yield()spinwait()會導致我的應用在我的 PC 上運行高達 50%。 使用Sleep(1) ,我的 CPU 百分比保持在 6%。 有人告訴我我應該選擇Thread.Yield() ,但是 CPU 百分比的峰值困擾着我。 這樣的事情的最佳做法是什么?

Thread.Yield將中斷當前線程以允許其他線程執行工作。 但是,如果他們沒有任何工作要做,您的線程很快就會重新安排並繼續輪詢,從而100%利用1個核心。

使調用線程執行到另一個准備在當前處理器上運行的線程。 操作系統選擇要生成的線程。

Thread.Sleep將調度您的線程在睡眠時間到期后再次運行,從而大大降低CPU利用率。

阻止當前線程達到指定的毫秒數。

鑒於兩者之間的選擇, Thread.Sleep更適合您的任務。 但是,我同意@Bryan的評論,即Threading.Timer可以提供更優雅的解決方案。

為帖子回答這個問題:

這樣的事情的最佳做法是什么?

您似乎有SpinWait 結構的案例,該結構自 .NET 4.0 起就存在,並且與更舊的SpinWait 方法不同。

你的代碼可以升級到這樣的:

var timeout = DateTime.Now.AddSeconds(3);
var spinWait = new SpinWait();
while (System.Status != Status.Complete
       && DateTime.Now < timeout
       && !_Worker.CancellationPending)
{
    spinWait.SpinOnce();
}

SpinOnce方法將決定是調用Thread.SleepThread.Yield還是在沒有 yield 的情況下進行“忙等待”。

具體關於帖子標題(即Thread.Sleep vs Thread.Yield),這里有一些最新的答案:

  • Thread.Yield() :如果有另一個線程准備好執行,那么這會將當前的 CPU 核心交給該線程。 否則什么都不做,即立即返回,如果系統至少有一個空閑的 CPU 內核,這可能會導致 CPU 高(和電池消耗高)。 在大多數情況下,會在同一個 CPU 內核中恢復執行,但由於多種原因(線程可能被 GC 掛起等),這並不能保證。 在服務器空間上,這是實現簡單繁忙等待的好方法,但在某些情況下它可能比上面解釋的SpinWait慢。 在 Windows 系統上,它(在撰寫本文時)實現為對 Win32 API SwitchToThread的調用。
  • Thread.Sleep(0) :如果隊列不為空,則將當前線程置於該優先級的 OS 准備執行隊列的末尾。 否則什么都不做,即立即返回。 該行為幾乎與Thread.Yield()相同,除了它允許切換 CPU 內核,這往往會在恢復之前為具有相同或更低優先級的線程提供更多時間。 除了這個額外的時間,在不同的 CPU 內核上恢復的幾率要大得多,導致 L1 或 L2 緩存等內容丟失,並進一步降低性能。 僅當飢餓幾率高於使用Thread.Yield()時才應使用它。 在 Windows 系統上,它(在撰寫本文時)實現為對 Win32 API SleepEx的調用。
  • Thread.Sleep(1) :如果剩余的時間片至少有 1 毫秒,則為剩余的時間片讓出 CPU。 否則,將 CPU 用於剩余時間片和整個下一個時間片。 因為在許多系統中時間片大約為 15 毫秒,它傾向於平均睡眠大約 7 毫秒或 8 毫秒。 因此,與Thread.Yield()Thread.Sleep(0)不同, Thread.Sleep(1)保證在一段時間內放棄 CPU,這可能會使事情降溫。 然而,性能成本是巨大的,因此它只能與其他“旋轉”或“屈服”解決方案結合使用。

對此的補充評論:

但是 CPU 百分比的峰值困擾着我

從您的帖子來看,這種擔憂可能是因為代碼有 3 秒超時。 SpinWait應該解決這個問題,但由於某種原因您不能使用SpinWait結構,請考慮使用較小的超時,以毫秒為單位。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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