繁体   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