Comment puis-je débloquer les discussions qui ont appelé la méthode WaitOne sur un AutoResetEvent objet?
Ci-dessous est une classe ayant la méthode 'SomeMethod" qui illustre mon problème.
class SomeClass
{
AutoResetEvent theEvent = new AutoResetEvent(false);
//more member declarations
public void SomeMethod()
{
//some code
theEvent.WaitOne();
//more code
}
}
La méthode est conçue pour être thread-safe et sera appelé dans des threads différents. Maintenant, ma question est comment est-il possible de débloquer toutes les discussions qui ont appelé le "WaitOne de la méthode sur le theEvent' objet à n'importe quel moment? Cette exigence se pose fréquemment dans ma conception parce que j'ai besoin pour être en mesure d'arrêter et de démarrer mon programme multi-threadé. Il me semble qu'il est assez simple de commencer un programme multi-threadé, mais difficile à arrêter.
Voici ce que j'ai essayé jusqu'à présent qui fonctionne apparemment. Mais est-ce l'approche standard?
public void UnblockAll()
{
do
{
theEvent.Set();
} while (theEvent.WaitOne(0));
}
Le "UnblockAll méthode est un membre de la "SomeClass" classe. La technique utilisée ici est basée sur la documentation MSDN de la Méthode WaitOne. Je cite la partie pertinente de la documentation ci-dessous:
Si millisecondsTimeout est égale à zéro, la méthode ne prend pas en bloc. Il teste l'état de la le d'attente de la poignée et retourne immédiatement.
Dans la boucle do..while, j'appelle le La méthode de jeu. Cela libère un seul thread qui a peut-être bloqué en raison d'un appel à la méthode WaitOne (codé à l'intérieur de la 'SomeMethod de la méthode). Ensuite, j'ai tester l'état de la "theEvent' objet juste pour savoir si c'est signalée. Ce test se fait en appelant la version surchargée de la méthode WaitOne qui prend le temps de paramètre. L'argument que j'utilise lorsque j'appelle la méthode WaitOne est égal à zéro, conformément à la documentation des résultats de l'appel de retourner immédiatement avec une valeur booléenne. Si la valeur de retour est true, alors le 'theEvent' objet était dans un signalé état. Si il y a au moins un seul thread bloqué sur l'appel à la "WaitOne" méthode "dans le" SomeMethod "méthode", l'appel à l'Ensemble de la méthode (codé à l'intérieur de la 'UnblockAll " méthode") serait le débloquer. Par conséquent, l'appel à la "WaitOne' méthode à la fin de l'instruction do..while dans le "UnblockAll' méthode retourne false. La valeur de retour n'est vrai que si il n'y avait pas de threads bloqués.
Est le raisonnement ci-dessus à droite et si c'est bon, c'est la technique standard de façon à faire face à mon problème? Je suis en train d'utiliser la solution principalement sur l' .net compact framework 2.0 de la plateforme.
On dirait que vous voulez un ManualResetEvent à la place. De cette façon il va rester ensemble, même si vous disposez de plusieurs auditeurs.
corrigé les erreurs de syntaxe dans le code..
OriginalL'auteur ghd | 2011-05-09
Vous devez vous connecter pour publier un commentaire.
Vous avez trois options viables. Chacun a ses propres avantages et inconvénients. Choisissez celui qui fonctionne le mieux pour votre situation spécifique.
Option 1 - interroger le
WaitHandle
.Au lieu de faire un indéfinie appel de blocage utiliser un avec un délai d'attente et de rétablir le bloc si une demande d'arrêt n'a pas été donné.
Option 2 - Utiliser un
WaitHandle
pour demander l'arrêtOption 3 - Utilisation
Thread.Interrupt
À ne pas confondre avec
Thread.Abort
. L'abandon d'un thread est certainement dangereux, mais interrompre un thread est complètement différent.Thread.Interrupt
va "pousser" la builtin appels bloquants utilisés dans la BCL, y comprisThread.Join
,WaitHandle.WaitOne
,Thread.Sleep
, etc..Net compact framework 2.0 n'ont pas le WaitAny méthode dans son WaitHandle classe 🙁
Trop mauvais. En passant, j'ai oublié de mentionner une autre option. J'ai édité ma réponse.
Interruption n'est pas sûr si vous appelez dans le code vous ne possédez pas. Vous pouvez interrompre les autres peuples attend.
Ouais, bon point.
OriginalL'auteur Brian Gideon
Votre routine va probablement travailler la plupart du temps, mais je ne pense pas qu'il n'y a aucune garantie que l'un des threads en attente de réinitialisation de l'événement entre le moment où votre arrêt boucle fixe et le temps de votre arrêt de la boucle vérifie à nouveau.
Je trouve que les classes AutoResetEvent et ManualResetEvent grand travail pour vraiment les scénarios simples. De tout temps il y a quelque chose d'étrange à propos de l', j'ai rapidement passer à la plus flexible Attendre Et d'Impulsion de modèle.
Si vous n'avez pas besoin de tout nettoyer, vous pourriez faire votre threads threads d'arrière-plan, et puis ils ne s'arrêtera que lorsque le thread principal de sorties.
Vous pourriez également être en mesure de définir une deuxième ManualResetEvent appelé stopRequest et d'attendre sur un signal de l'un ou l'autre cas. Toutefois, cela pourrait ne pas être pris en charge sur le compact framework.
Tout le programme est organisé en un ensemble de coopérant 'composants'. Certains de ces composants sont utilisés par plusieurs threads. Je sens que si je leur fournir un moyen pour normalement l'arrêt d'un composant, sans nuire à d'autres composants, mon dessin n'est pas complète. Ce qui rend les threads d'arrière-plan est ma dernière option.
Je vais certainement donner la possibilité d'utiliser une deuxième ManualResetEvent un essai..
OriginalL'auteur Don Kirkby
Ne abandon de thread de travail pour votre cadre?
OriginalL'auteur Jay