web-dev-qa-db-ja.com

ループせずにブール値を待つ方法(待機/セマフォ/イベント/ミューテックスなどを使用)

別のスレッドがブール値を設定するまでスレッドを停止する必要がありますそして、それらの間でイベントを共有したくない

私が現在持っているのは、Sleepを使用した次のコードです(これが変更したいコードです)。

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

何か案は?

説明を明確にするために編集:

私が所有していないクラスの_engineというオブジェクトがあります。私はそれを修正することはできません、それが私が彼らの間でイベントを共有したくない理由です。そのクラスのメソッドがtrueを返すまで待つ必要があります。

19

SpinWait.SpinUntilが正しい答えです。このコードをどこに配置するかは関係ありません。 SpinUntilは "呼び出し間での回転、制御、スリープの素晴らしい組み合わせ" を提供します。

26
MoonStom

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();
12
Tigran

宣言する

 AutoResetEvent _ReadyToStop = new AutoResetEvent(false);

そしてとして使用

 _ReadyToStop.WaitOne();

そして

 _ReadyToStop.Set();

詳細は 。Netの同期プリミティブ を参照してください

4
L.B

条件変数は、条件を待機するために使用できる同期プリミティブです。

.NETにはネイティブには存在しません。ただし、次の link は、SemaphoreSlim、AutoResetEvent、およびMonitorクラスに関して実装された条件変数クラスに100%マネージコードを提供します。これにより、スレッドは条件を待機できます。また、条件が満たされたときに1つ以上のスレッドを起動できます。さらに、タイムアウトと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;
  }
}

次に、別のスレッドで、条件待ちの1つ以上のスレッドをウェイクアップできます。

lock(queueLock) {

  //..add item here

  notEmptyCondition.Pulse(); // or PulseAll
}
0
gm127