Thread.Sleep或Thread.Yield

poc*_*oco 26 c# multithreading sleep 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);
}
Run Code Online (Sandbox Code Playgroud)

当看着我的CPU%,yield()spinwait()导致我的应用程序来拍摄高达50%,我的电脑上.随着Sleep(1)我的CPU%,6%,保持了下来.我被告知我应该选择Thread.Yield(),但是CPU%的高峰会让我感到困扰.什么是这样的最佳做法?

Eri*_* J. 28

Thread.Yield将中断当前线程以允许其他线程执行工作.但是,如果他们没有任何工作要做,您的线程很快就会重新安排并继续轮询,从而100%利用1个核心.

使调用线程执行到另一个准备在当前处理器上运行的线程.操作系统选择要生成的线程.

Thread.Sleep将调度您的线程在睡眠时间到期后再次运行,从而大大降低CPU利用率.

阻止当前线程达到指定的毫秒数.

鉴于两者之间的选择,Thread.Sleep更适合您的任务.但是,我同意@Bryan的评论,即Threading.Timer一个更优雅的解决方案.

  • 这两种涉及轮询的解决方案都远非“优雅”。仅当绝对没有其他方式与 DLL 通信时,才应使用这种解决方案,例如。它是第三方的、不透明的、设计糟糕的(在这种情况下,设计师应该被操作系统手册反复敲打:)。 (2认同)
  • Thread.Yield 实际上告诉操作系统从进程中获取优先权(而不是 Thread.Sleep,后者让操作系统自行解决)。当我使用 Thread.Yield 时,我将它与 Thread.Sleep 结合起来——所以代码基本上是 `Thread.Yield(); Thread.Sleep(1);` -- 请注意,Thread.Sleep 几乎总是休眠至少 10 毫秒(我还没有找到一种方法,可以在不使用非托管代码或第三方库的情况下获得比 10 毫秒更好的计时分辨率)。 (2认同)