web-dev-qa-db-fra.com

Comment attendre un booléen sans boucler (en utilisant n'importe quel type de wait/semaphore/event/mutex, etc.)

Je dois arrêter un thread jusqu'à ce qu'un autre thread définisse une valeur booléenne et je ne souhaite pas partager entre eux un événement .

Ce que j'ai actuellement est le code suivant utilisant un sommeil (et c'est le code que je veux changer):

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

Des idées?

Editer pour clarifier les choses:

Il y a un objet appelé _engine d'une classe que je ne possède pas. Je ne peux pas le modifier, c'est pourquoi je ne veux pas partager un événement entre eux. J'ai besoin d'attendre qu'une méthode de cette classe retourne true.

16

SpinWait.SpinUntil est la bonne réponse, peu importe où vous allez placer ce code. SpinUntil offre "un joli mélange de rotation, de rendement et de sommeil entre les invocations" .

24
MoonStom

Si vous utilisez C# 4.0, vous pouvez utiliser:

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

En utilisant Task.Wait méthode.

Si vous avez plusieurs tâches exécutées l'une après l'autre, vous pouvez utiliser Task.ContinueWith :

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

déclarer comme

 AutoResetEvent _ReadyToStop = new AutoResetEvent(false);

et utiliser comme

 _ReadyToStop.WaitOne();

et 

 _ReadyToStop.Set();

Pour plus d'informations, voir Primitives de synchronisation dans .Net

4
L.B

Une variable de condition est la primitive de synchronisation que vous pouvez utiliser pour attendre une condition. 

Il n’existe pas nativement dans .NET. Mais le link suivant fournit du code 100% géré pour une classe de variable de condition implémentée en termes de classes SemaphoreSlim, AutoResetEvent et Monitor. Cela permet au thread d'attendre une condition. Et peut réveiller un ou plusieurs threads lorsque la condition est remplie. En outre, il prend en charge les délais d’expiration et AnnulationTokens.

Pour attendre, vous écrivez un code semblable à celui-ci:

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

Ensuite, dans un autre thread, vous pouvez réactiver un ou plusieurs threads en attente de condition.

lock(queueLock) {

  //..add item here

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