是否有效率?
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建议的那样一起忙碌地等待。
发布于 2012-03-15 19:49:40
最好的方法是有一些机制来主动检测(而不是被动地轮询它已经成为真的);这可以是任何类型的等待句柄,或者可能是带有Wait的Task,或者可能是你可以订阅的你自己的event。当然,如果你做了那种“等待,直到发生了什么事情”,也就是说,仍然不如简单地将下一步工作作为回调来完成,这意味着:你不需要使用线程来等待。Task为此提供了ContinueWith,或者当event被触发时,您可以直接在它中执行这项工作。根据上下文,event可能是最简单的方法。然而,Task已经提供了您在这里讨论的大部分内容,包括“带有超时的等待”和“回调”机制。
是的,旋转10秒并不是很好。如果你想使用像你现在的代码一样的东西,如果你有理由期待一个短的延迟,但需要考虑一个更长的延迟--比如20ms的SpinWait,剩下的使用Sleep?
Re注释;下面是我如何挂接一个“是否已满”机制:
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);
}
}使用,在"put back into the collection“代码中:
if(CollectionIsFull) {
lock(syncLock) {
if(CollectionIsFull) { // double-check with the lock
Monitor.PulseAll(syncLock);
}
}
}发布于 2012-03-15 20:08:09
在.NET 4中,SpinWait会执行10次CPU密集型旋转,然后才会让步。但是,它不会在每个周期之后立即返回给调用者;相反,它会调用Thread.SpinWait通过CLR (本质上是操作系统)旋转一段设定的时间段。这段时间最初是几十纳秒,但随着每次迭代而加倍,直到10次迭代完成。这可以在旋转(CPU密集型)阶段的总时间内实现清晰度/可预测性,系统可以根据条件(核心数量等)进行调整。如果SpinWait处于自旋产生阶段的时间太长,它将周期性地休眠,以允许其他线程继续(有关更多信息,请参阅J. Albahari's blog )。这个过程保证了核心的忙碌...
因此,SpinWait将CPU密集型旋转限制在一定的迭代次数内,之后它会在每次旋转上生成时间片(通过实际调用Thread.Yield和Thread.Sleep),从而降低其资源消耗。它还将检测用户是否正在运行单核心计算机,如果是,则在每个周期上让步。
使用Thread.Sleep时,线程会被阻塞。但就CPU而言,这个过程不会像上面那样昂贵。
https://stackoverflow.com/questions/9719003
复制相似问题