2010-05-21 8 views
6

je besoin d'un moyen de faire ce qui suit efficacement en C#:C# arrêt et continuer

Faire arrêter l'exécution du programme jusqu'à certaine valeur est modifiée.

Note: Je ne veux pas le faire avec une boucle while pour éviter de perdre le pouvoir cpu ..

Edit: Et je veux répondre aussi rapidement que possible après la valeur a changé ..

Editer: Ce sera dans ma méthode de classe qui est appelée par un autre code, mais la valeur à vérifier est dans ma classe ... La méthode est censée attendre que d'autres c ode évaluer et changer ma valeur .. il doit continuer à faire son travail .. malheureusement cela est fait plusieurs fois (donc je dois prendre soin de la performance)

+0

est cette application un service Windows? Vous ne spécifiez pas, et cela n'a pas vraiment de sens d'interrompre littéralement l'exécution dans une application interactive (pilotée par les événements). – Aaronaught

+5

Vos exigences sont contradictoires.Vous rejetez l'attente occupée en raison de sa consommation d'énergie, et vous exigez qu'elle soit ** aussi réactive que possible **, mais l'attente occupée est ce qui va être ** aussi réactif que possible **. Ce qui serait mieux, c'est si vous nous avez parlé de votre * budget *. "Aussi vite que possible" ne nous dit rien; "en une milliseconde" nous en dit beaucoup. Une solution qui réagit en moins d'une milliseconde peut être assez différente d'une solution répondant à une microseconde ou à une seconde. –

+1

qu'est-ce que vous voulez dire exactement par l'arrêt de l'exécution? est-ce un fil en cours d'exécution que vous devez interrompre à un certain point? comment comptez-vous l'arrêter? ou est-ce plus comme un court événement que vous aimeriez survenir lors d'un changement de valeur? –

Répondre

15
+0

Il n'y a pas de 'Monitor.Set'. Voulez-vous dire 'Monitor.Pulse' ou' Monitor.PulseAll'? – Aaronaught

+0

@ Aaronaught- oui, oui –

+0

Si vous voulez dormir complètement sans essorage, c'est la voie à suivre. Cependant, cela nécessite que le code qui définit la valeur sache comment impulser sur l'objet correct, sinon votre code ne se réveillera jamais. – Stephan

6
while(some-condition-here) 
{ 
    Thread.CurrentThread.Sleep(100); // Release CPU for 100ms 
} 

Il est appelé, je pense que spin-sommeil. Bien sûr, vous pouvez ajuster le 100 à ce que vous pensez être en forme. C'est essentiellement le délai d'attente pour chaque vérification.

Il existe d'autres façons de le faire, mais c'est la plus simple et la plus efficace.

Il est en fait référence dans ce e-book:

Threading in C# by Joseph Albahari: Part 2: Basic Synchronization

+0

Je l'ai déjà utilisé, mais je n'en suis pas fan. (donc je ne modifierai pas votre réponse de haut en bas.) Ça m'a toujours "senti" mal. – Pretzel

+0

@Pretzel J'ai référencé un livre (e-book) qui en parle. – Aren

+0

Juste parce que c'est dans un livre ne le rend pas juste. En outre, pour citer l'auteur, "peut-être sa plus grande utilisation est quand un programmeur a abandonné pour obtenir une construction de signalisation plus complexe à travailler!" –

7

Si la valeur que vous attendez est défini ailleurs dans la même application, vous pouvez utiliser une poignée d'attente:

AutoResetEvent waitHandle = new AutoResetEvent(); 
... 
//thread will sleep here until waitHandle.Set is called 
waitHandle.WaitOne(); 
... 
//this is where the value is set 
someVar = someValue; 
waitHandle.Set(); 

(notez que le WaitOne et Set doivent se produire sur des threads séparés comme WaitOne sera bloquer le fil sur lequel il est appelé)

Si vous n'avez pas accès au code qui change la valeur, la meilleure façon de le faire est, comme d'autres l'ont dit, d'utiliser une boucle pour vérifier si la valeur a changé et utilisez Thread.Sleep() pour ne pas utiliser le temps de processeur:

while(!valueIsSet) 
{ 
    Thread.Sleep(100); 
} 
+0

/agree ... c'est la meilleure façon possible – csauve

+0

Si le but est de BLOQUER un thread, c'est la meilleure façon. Pour bloquer le thread principal et empêcher toute nouvelle entrée jusqu'à ce que l'événement se produise, placez le .WaitOne() dans le thread principal. Dans un autre thread, où la valeur qui déclenche le réveil, placez le .Set(); – Roast

3

Vous pouvez utiliser le motif de conception Observer. Il est conçu pour résoudre des problèmes comme le vôtre.

Ce motif contient principalement un sujet et un observateur. Vous pouvez l'avoir pour répondre à tout changement et très rapidement.

Vous pouvez trouver plus d'informations et des exemples de code here

+0

Si l'architecture le permet (c'est-à-dire que vous avez le contrôle sur ce que vous surveillez), cela peut être une bonne solution. Vous obtenez une réponse très rapide parce que vous recevez l'événement juste après le changement. La principale mise en garde est que vous exécutez dans le contexte du thread qui a effectué le changement, ce qui peut parfois être problématique. –