SpinWait与睡眠等待。 哪一个使用?

是否有效?

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所build议的那样,我宁愿避免忙于等待。

最好的办法是有一些机制来积极地检测事情是否成真(而不是被动地投票,事实已经成为现实)。 这可能是任何types的等待处理,或者可能是一个Task Wait ,或者一个event ,你可以订阅来解开自己。 当然,如果你这样做“等到某个事情发生”,那还不如完成下一个工作作为callback的效率,这意味着:你不需要使用一个线程来等待。 为此, Task已经ContinueWith ,或者您可以在event被触发时执行该Taskevent可能是最简单的方法,取决于上下文。 然而, Task已经提供了大部分你在这里讨论的东西,包括“等待超时”和“callback”机制。

是的,旋转10秒并不是很好。 如果你想使用类似你当前的代码,如果你有理由期望一个短暂的延迟,但需要允许更长的一个 – 也许SpinWait (说)20ms,并使用Sleeprest?


重新评论; 这里是我如何挂钩“是完全”的机制:

 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); } } 

在“放回collections”代码中:

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

在.NET 4中, SpinWait在执行10次迭代之前执行CPU密集型旋转。 但是在每个循环之后它不会立即返回给调用者。 相反,它调用Thread.SpinWait通过CLR(本质上是OS)旋转一段时间。 这个时间段最初是几十纳秒,但是每次迭代加倍,直到10次迭代完成。 这使得在纺纱(CPU密集型)阶段花费的总时间(系统可根据条件(内核数量等)调整)中可以清晰/可预测。 如果SpinWait处于旋转屈服阶段,它将定期hibernate以允许其他线程进行(参见J. Albahari的博客以获取更多信息)。 这个过程是保证一个核心忙…

因此, SpinWait将CPU密集型的旋转限制到一定数量的迭代,然后在每次旋转时产生时间片(通过实际调用Thread.YieldThread.Sleep ),降低资源消耗。 它也将检测用户是否正在运行单个核心机器,并且如果是这种情况,则在每个周期中产生。

Thread.Sleep线程被阻塞。 但是这个过程并不像CPU那样昂贵。