【问题标题】:Thread.Sleep or Thread.YieldThread.Sleep 或 Thread.Yield
【发布时间】:2012-07-13 22:04:19
【问题描述】:

我有一个方法使用后台工作程序来轮询 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 百分比的峰值困扰着我。这种情况的最佳做法是什么?

【问题讨论】:

  • 您是否考虑在此轮询过程中使用Threading.Timer?如果您使用的是 .NET 4.0,则可以将其与 TPL 混合以进行基于任务的协作取消。
  • 我猜你的电脑上有 2 个内核。其中一个是 100% 忙...
  • 为什么只使用后台工作人员来等待它?这违背了所有常识。如果您需要,为什么 DLL 不提供一种明智的方式来等待操作完成?
  • +1 @DavidSchwartz 建议使用有效的信号而不是浪费 CPU 和延迟的轮询(还有很多,AutoResetEvent、Semaphore 等)。
  • @poco tl;dr 你被告知

标签: c# multithreading sleep yield


【解决方案1】:

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

使调用线程将执行让给准备在当前处理器上运行的另一个线程。操作系统选择要让步的线程。

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

阻塞当前线程指定的毫秒数。

鉴于两者之间的选择,Thread.Sleep 更适合您的任务。不过,我同意 @Bryan 的评论,即 Threading.Timer 可以提供更优雅的解决方案。

【讨论】:

  • 两种涉及轮询的解决方案都不是远程“优雅”的。只有在绝对没有其他方式与 DLL 通信时,才应在绝望中使用这种解决方案,例如。它是第 3 方的,不透明且设计糟糕,(在这种情况下,应该用操作系统手册反复打击设计师的头部:)。
  • 当然。当问题表明必须轮询外部 DLL 时,我假设了这个约束。
  • Thread.Yield 实际上告诉操作系统从您的进程中获取优先级(而不是 Thread.Sleep,它使操作系统自己解决问题)。当我使用 Thread.Yield 时,我将它与 Thread.Sleep 结合使用——所以代码基本上是 Thread.Yield(); Thread.Sleep(1);——请注意,Thread.Sleep 几乎总是会休眠至少 10 毫秒(我还没有看到更好的方法不使用非托管代码或第三方库的时间分辨率超过 10 毫秒)。
  • 你有关于这个 10 毫秒最小延迟的资料吗?当间隔设置为零时,我们在运行 Thread.Sleep(interval) 时遇到问题。
猜你喜欢
  • 2010-11-27
  • 2011-02-26
  • 1970-01-01
  • 2011-06-17
  • 1970-01-01
  • 1970-01-01
  • 2019-03-31
  • 2014-07-02
  • 1970-01-01
相关资源
最近更新 更多