J'ai lu la documentation à ce sujet et je pense avoir compris. Un se AutoResetEvent
réinitialise lorsque le code passeevent.WaitOne()
, mais ManualResetEvent
pas.
Est-ce correct?
c#
.net
multithreading
autoresetevent
manualresetevent
Ben McNiel
la source
la source
Réponses:
Oui. C'est comme la différence entre un péage et une porte. C'est
ManualResetEvent
la porte qui doit être fermée (réinitialisée) manuellement. IlAutoResetEvent
s'agit d'un péage, permettant à une voiture de passer et se fermant automatiquement avant que la suivante puisse passer.la source
Imaginez simplement que le
AutoResetEvent
exécuteWaitOne()
etReset()
comme une seule opération atomique.la source
La reponse courte est oui. La différence la plus importante est qu'un AutoResetEvent ne permettra à un seul thread en attente de continuer. Un événement ManualResetEvent, d'autre part, continuera à permettre aux threads, plusieurs en même temps, de continuer jusqu'à ce que vous lui disiez de s'arrêter (réinitialisez-le).
la source
Filetage en C # - E-Book gratuit
Un ManualResetEvent est une variante d'AutoResetEvent. Il diffère par le fait qu'il ne se réinitialise pas automatiquement une fois qu'un thread est passé à travers un appel WaitOne, et fonctionne donc comme une porte: l'appel de Set ouvre la porte, autorisant n'importe quel nombre de threads que WaitOne à la porte traverse; L'appel à Reset ferme la porte, provoquant potentiellement une file d'attente de serveurs jusqu'à sa prochaine ouverture.
On pourrait simuler cette fonctionnalité avec un champ booléen "gateOpen" (déclaré avec le mot-clé volatile) en combinaison avec "spin-sleep" - en vérifiant à plusieurs reprises le drapeau, puis en dormant pendant une courte période.
ManualResetEvents sont parfois utilisés pour signaler qu'une opération particulière est terminée, ou que l'initialisation d'un thread est terminée et est prête à effectuer le travail.
la source
J'ai créé des exemples simples pour clarifier la compréhension de
ManualResetEvent
vsAutoResetEvent
.AutoResetEvent
: supposons que vous ayez 3 threads de travail. Si l'un de ces threads appelleWaitOne()
les 2 autres threads, l'exécution s'arrête et attend le signal. Je suppose qu'ils utilisentWaitOne()
. C'est comme; si je ne travaille pas, personne ne travaille. Dans le premier exemple, vous pouvez voir queLorsque vous appelez,
Set()
tous les threads fonctionnent et attendent le signal. Après 1 seconde, j'envoie un deuxième signal et ils s'exécutent et attendent (WaitOne()
). Pensez à ces gars-là sont des joueurs d'équipe de football et si un joueur dit que j'attendrai que le manager m'appelle, et que les autres attendent que le manager leur dise de continuer (Set()
)Dans cet exemple, vous pouvez clairement voir que lorsque vous appuyez pour la première fois,
Set()
tous les threads disparaissent, puis après 1 seconde, il signale à tous les threads d'attendre! Dès que vous les redéfinissez, quel que soit leur appelWaitOne()
, ils continueront de fonctionner car vous devez appeler manuellementReset()
pour les arrêter tous.Il s'agit davantage de la relation Arbitre / Joueurs là-bas, indépendamment du fait qu'un joueur soit blessé et attendre que les autres continuent de fonctionner. Si l'arbitre dit wait (
Reset()
), tous les joueurs attendront le signal suivant.la source
autoResetEvent.WaitOne()
est similaire à
comme une opération atomique
la source
OK, normalement, ce n'est pas une bonne pratique d'ajouter 2 réponses dans le même fil, mais je ne voulais pas modifier / supprimer ma réponse précédente, car cela peut aider d'une autre manière.
Maintenant, j'ai créé un extrait d'application de console run-to-learn, beaucoup plus complet et facile à comprendre ci-dessous.
Exécutez simplement les exemples sur deux consoles différentes et observez le comportement. Vous aurez une idée beaucoup plus claire de ce qui se passe dans les coulisses.
Événement de réinitialisation manuelle
Événement de réinitialisation automatique
la source
AutoResetEvent conserve une variable booléenne en mémoire. Si la variable booléenne est fausse, elle bloque le thread et si la variable booléenne est vraie, elle débloque le thread.
Lorsque nous instancions un objet AutoResetEvent, nous transmettons la valeur par défaut de la valeur booléenne dans le constructeur. Vous trouverez ci-dessous la syntaxe d'instanciation d'un objet AutoResetEvent.
Méthode WaitOne
Cette méthode bloque le thread actuel et attend le signal par un autre thread. La méthode WaitOne place le thread actuel dans un état de thread de veille. La méthode WaitOne renvoie true si elle reçoit le signal, sinon renvoie false.
La deuxième surcharge de la méthode WaitOne attend le nombre de secondes spécifié. S'il n'obtient aucun fil de signal continue son travail.
Nous avons appelé la méthode WaitOne en passant les 2 secondes comme arguments. Dans la boucle while, il attend le signal pendant 2 secondes puis continue son travail. Lorsque le thread a obtenu le signal WaitOne retourne vrai et quitte la boucle et affiche le "Thread got signal".
Définir la méthode
La méthode AutoResetEvent Set a envoyé le signal au thread en attente pour poursuivre son travail. Voici la syntaxe de l'appel de la méthode Set.
ManualResetEvent conserve une variable booléenne en mémoire. Lorsque la variable booléenne est fausse, elle bloque tous les threads et lorsque la variable booléenne est vraie, elle débloque tous les threads.
Lorsque nous instancions un ManualResetEvent, nous l'initialisons avec la valeur booléenne par défaut.
Dans le code ci-dessus, nous initialisons le ManualResetEvent avec une valeur fausse, ce qui signifie que tous les threads qui appellent la méthode WaitOne seront bloqués jusqu'à ce que certains threads appellent la méthode Set ().
Si nous initialisons ManualResetEvent avec la valeur true, tous les threads qui appellent la méthode WaitOne ne seront pas bloqués et libres de continuer.
Méthode WaitOne
Cette méthode bloque le thread actuel et attend le signal par un autre thread. Il retourne vrai s'il reçoit un signal, sinon renvoie faux.
Voici la syntaxe de l'appel de la méthode WaitOne.
Dans la deuxième surcharge de la méthode WaitOne, nous pouvons spécifier l'intervalle de temps jusqu'à ce que le thread actuel attende le signal. Si dans le temps interne, il ne reçoit pas de signal, il retourne faux et passe à la ligne de méthode suivante.
Voici la syntaxe de l'appel de la méthode WaitOne avec intervalle de temps.
Nous avons spécifié 5 secondes dans la méthode WaitOne. Si l'objet manualResetEvent ne reçoit pas de signal entre 5 secondes, il définit la variable isSignalled sur false.
Définir la méthode
Cette méthode est utilisée pour envoyer le signal à tous les threads en attente. La méthode Set () définit la variable booléenne de l'objet ManualResetEvent sur true. Tous les threads en attente sont débloqués et continuent.
Voici la syntaxe de l'appel de la méthode Set ().
Méthode de réinitialisation
Une fois que nous appelons la méthode Set () sur l'objet ManualResetEvent, son booléen reste vrai. Pour réinitialiser la valeur, nous pouvons utiliser la méthode Reset (). La méthode de réinitialisation remplace la valeur booléenne par false.
Voici la syntaxe de l'appel de la méthode Reset.
Nous devons immédiatement appeler la méthode Reset après avoir appelé la méthode Set si nous voulons envoyer plusieurs fois le signal aux threads.
la source
Oui. C'est absolument correct.
Vous pouvez voir ManualResetEvent comme un moyen d'indiquer l'état. Quelque chose est activé (défini) ou désactivé (réinitialisé). Un événement d'une certaine durée. Tout thread en attente de cet état peut se poursuivre.
Un AutoResetEvent est plus comparable à un signal. Une indication unique que quelque chose s'est produit. Un événement sans durée. En règle générale, mais pas nécessairement, le «quelque chose» qui s'est produit est petit et doit être géré par un seul thread - d'où la réinitialisation automatique après qu'un seul thread a consommé l'événement.
la source
Oui c'est vrai.
Vous pouvez vous faire une idée en utilisant ces deux.
Si vous devez dire que vous avez terminé certains travaux et que d'autres (threads) en attente peuvent maintenant continuer, vous devez utiliser ManualResetEvent.
Si vous devez avoir un accès exclusif mutuel à n'importe quelle ressource, vous devez utiliser AutoResetEvent.
la source
Si vous voulez comprendre AutoResetEvent et ManualResetEvent, vous devez comprendre non pas le threading mais les interruptions!
.NET veut évoquer une programmation de bas niveau la plus éloignée possible.
Une interruption est quelque chose utilisé dans la programmation de bas niveau qui équivaut à un signal qui de bas est devenu haut (ou vice versa). Lorsque cela se produit, le programme interrompt son exécution normale et déplace le pointeur d'exécution vers la fonction qui gère cet événement .
La première chose à faire en cas d'interruption est de réinitialiser son état, car le matériel fonctionne de cette façon:
C'est la différence entre ManualResetEvent et AutoResetEvent.
Si un événement ManualResetEvent se produit et que je ne le réinitialise pas, la prochaine fois que cela se produit, je ne pourrai pas l'écouter.
la source