如何在不循环的情况下等待布尔值(使用任何类型的等待/信号量/事件/互斥等)



我需要停止一个线程,直到另一个线程设置布尔值,并且我不想在它们之间共享事件

我目前使用的是以下使用睡眠的代码(这是我想要更改的代码):

while (!_engine.IsReadyToStop())
{
    System.Threading.Thread.Sleep(Properties.Settings.Default.IntervalForCheckingEngine); 
}

有什么想法吗?

编辑以澄清:

有一个类的名为_engine的对象,我不拥有它。我不能修改它,这就是为什么我不想在他们之间分享一个事件。我需要等到该类的一个方法返回true。

SpinWait.SpinUntil是正确的答案,无论您将把代码放在哪里。SpinUntil提供了"在调用之间旋转、屈服和睡眠的良好组合"。

如果使用C# 4.0,可以使用:

Task t = Task.Factory.StartNew (() => SomeCall(..));
t.Wait();

通过使用Task.Wait方法。

如果你有多个任务一个接一个地运行,你可以使用task.ContinueWith:

 Task t = Task.Factory.StartNew (() =>SomeCall(..)).
                                ContinueWith(ExecuteAfterThisTaskFinishes(...);
 t.Wait();

声明为

 AutoResetEvent _ReadyToStop = new AutoResetEvent(false);

并用作

 _ReadyToStop.WaitOne();

 _ReadyToStop.Set();

有关更多信息,请参阅.Net 中的同步原语

条件变量是用于等待条件的同步原语。

它本身并不存在于.NET中。但以下链接为根据SemaphoreSlim、AutoResetEvent和Monitor类实现的条件变量类提供了100%托管代码。它允许线程等待某个条件。并且可以在条件满足时唤醒一个或多个线程。此外,它还支持超时和CancellationTokens。

要等待一个条件,您可以编写类似以下的代码:

object queueLock = new object();
ConditionVariable notEmptyCondition = new ConditionVariable();
T Take() {
  lock(queueLock) {
    while(queue.Count == 0) {
      // wait for queue to be not empty
      notEmptyCondition.Wait(queueLock);
    }
    T item = queue.Dequeue();
    if(queue.Count < 100) {
      // notify producer queue not full anymore
      notFullCondition.Pulse();
    }
    return item;
  }
}

然后在另一个线程中,您可以唤醒一个或多个等待条件的线程。

lock(queueLock) {
  //..add item here
  notEmptyCondition.Pulse(); // or PulseAll
}

最新更新