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
被触发时执行该Task
。 event
可能是最简单的方法,取决于上下文。 然而, Task
已经提供了大部分你在这里讨论的东西,包括“等待超时”和“callback”机制。
是的,旋转10秒并不是很好。 如果你想使用类似你当前的代码,如果你有理由期望一个短暂的延迟,但需要允许更长的一个 – 也许SpinWait
(说)20ms,并使用Sleep
rest?
重新评论; 这里是我如何挂钩“是完全”的机制:
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.Yield
和Thread.Sleep
),降低资源消耗。 它也将检测用户是否正在运行单个核心机器,并且如果是这种情况,则在每个周期中产生。
用Thread.Sleep
线程被阻塞。 但是这个过程并不像CPU那样昂贵。