[英]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.Sleep
、 Thread.Yield
還是在沒有 yield 的情況下進行“忙等待”。
具體關於帖子標題(即Thread.Sleep vs Thread.Yield),這里有一些最新的答案:
SpinWait
慢。 在 Windows 系統上,它(在撰寫本文時)實現為對 Win32 API SwitchToThread的調用。Thread.Yield()
相同,除了它允許切換 CPU 內核,這往往會在恢復之前為具有相同或更低優先級的線程提供更多時間。 除了這個額外的時間,在不同的 CPU 內核上恢復的幾率要大得多,導致 L1 或 L2 緩存等內容丟失,並進一步降低性能。 僅當飢餓幾率高於使用Thread.Yield()
時才應使用它。 在 Windows 系統上,它(在撰寫本文時)實現為對 Win32 API SleepEx的調用。Thread.Yield()
和Thread.Sleep(0)
不同, Thread.Sleep(1)
保證在一段時間內放棄 CPU,這可能會使事情降溫。 然而,性能成本是巨大的,因此它只能與其他“旋轉”或“屈服”解決方案結合使用。對此的補充評論:
但是 CPU 百分比的峰值困擾着我
從您的帖子來看,這種擔憂可能是因為代碼有 3 秒超時。 SpinWait
應該解決這個問題,但由於某種原因您不能使用SpinWait
結構,請考慮使用較小的超時,以毫秒為單位。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.