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建议的那样,一起忙碌地等待。
在.NET 4中,SpinWait
在屈服之前执行10次CPU密集型旋转。但在每个周期之后,它不会立即返回给调用者;相反,它调用Thread.SpinWait
通过CLR(本质上是OS)旋转一段设定的时间。这个时间段最初是几十纳秒,但每次迭代都会翻倍,直到10次迭代完成。这使得旋转(CPU密集型)阶段的总时间变得清晰/可预测,系统可以根据条件(内核数量等)对其进行调整。如果SpinWait
在旋转屈服阶段停留的时间过长,它将周期性地休眠,以允许其他线程继续进行(更多信息,请参阅J.Albahari的博客)。这个过程保证了核心的忙碌。。。
因此,SpinWait
将CPU密集型旋转限制在一组迭代次数内,之后它在每次旋转时产生时间片(通过实际调用Thread.Yield
和Thread.Sleep
),从而降低了资源消耗。它还将检测用户是否在运行单芯机器,如果是这样的话,它将在每个循环中产生产量。
使用Thread.Sleep
时,线程被阻塞。但就CPU而言,这个过程不会像上面那样昂贵。
最好的方法是有一些机制来主动检测事情变为真(而不是被动轮询是否变为真);这可以是任何类型的等待句柄,也可以是带有Wait
的Task
,或者可以是您可以订阅以解除绑定的event
。当然,如果你做了那种"等到事情发生",也就是说仍然不如简单地将下一步工作作为回调来完成,这意味着:你不需要使用线程来等待。Task
有ContinueWith
,或者你可以在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);
}
}
}