SpinWait与Sleep wait.使用哪一个

本文关键字:哪一个 wait Sleep SpinWait | 更新日期: 2023-09-27 18:27:49

是否有效

SpinWait.SpinUntil(() => myPredicate(), 10000)

超时10000ms

对相同条件使用Thread.Sleep轮询是否更有效例如,以下SleepWait函数所示的内容:

public bool SleepWait(int timeOut)
{
    Stopwatch stopwatch = new Stopwatch(); 
    stopwatch.Start();
    while (!myPredicate() && stopwatch.ElapsedMilliseconds < timeOut)
    {
       Thread.Sleep(50)
    }  
    return myPredicate()
}

我担心,如果我们谈论的是超过1秒的超时,那么SpinWait的所有屈服可能不是一个好的使用模式?这是一个有效的假设吗?

你更喜欢哪种方法,为什么?还有更好的方法吗?


更新-变得更加具体:

当BlockingCollection脉冲达到有限制的容量时,有没有办法让它成为一个休眠线程?我宁愿避免像Marc Gravel建议的那样,一起忙碌地等待。

SpinWait与Sleep wait.使用哪一个

在.NET 4中,SpinWait在屈服之前执行10次CPU密集型旋转。但在每个周期之后,它不会立即返回给调用者;相反,它调用Thread.SpinWait通过CLR(本质上是OS)旋转一段设定的时间。这个时间段最初是几十纳秒,但每次迭代都会翻倍,直到10次迭代完成。这使得旋转(CPU密集型)阶段的总时间变得清晰/可预测,系统可以根据条件(内核数量等)对其进行调整。如果SpinWait在旋转屈服阶段停留的时间过长,它将周期性地休眠,以允许其他线程继续进行(更多信息,请参阅J.Albahari的博客)。这个过程保证了核心的忙碌。。。

因此,SpinWait将CPU密集型旋转限制在一组迭代次数内,之后它在每次旋转时产生时间片(通过实际调用Thread.YieldThread.Sleep),从而降低了资源消耗。它还将检测用户是否在运行单芯机器,如果是这样的话,它将在每个循环中产生产量。

使用Thread.Sleep时,线程被阻塞。但就CPU而言,这个过程不会像上面那样昂贵。

最好的方法是有一些机制来主动检测事情变为真(而不是被动轮询是否变为真);这可以是任何类型的等待句柄,也可以是带有WaitTask,或者可以是您可以订阅以解除绑定的event。当然,如果你做了那种"等到事情发生",也就是说仍然不如简单地将下一步工作作为回调来完成,这意味着:你不需要使用线程来等待。TaskContinueWith,或者你可以在event被解雇时在它中完成工作。event可能是最简单的方法,具体取决于上下文。然而,Task已经提供了您在这里谈论的大部分内容,包括"带超时的等待"answers"回调"机制。

是的,旋转10秒并不好。如果你想使用像你当前代码一样的东西,如果你有理由期待一个短的延迟,但需要允许更长的延迟——也许SpinWait(比如)20ms,其余的使用Sleep


回复评论;以下是我如何勾选"满了吗"机制:

private readonly object syncLock = new object();
public bool WaitUntilFull(int timeout) {
    if(CollectionIsFull) return true; // I'm assuming we can call this safely
    lock(syncLock) {
        if(CollectionIsFull) return true;
        return Monitor.Wait(syncLock, timeout);
    }
}

带有,在"放回收藏"代码中:

if(CollectionIsFull) {
    lock(syncLock) {
        if(CollectionIsFull) { // double-check with the lock
            Monitor.PulseAll(syncLock);
        }
    }
}