Maison développement back-end Tutoriel C#.Net Synchronisation .NET et EventWaitHandle asynchrone

Synchronisation .NET et EventWaitHandle asynchrone

Apr 11, 2017 pm 02:05 PM


Dans l'article précédent nous avons évoqué Mutex et les protagonistes de cet article directement ou indirectement Hérite de WaitHandle :

WaitHandle propose plusieurs méthodes de synchronisation. Le blog précédent sur Mutex a déjà mentionné une WaitOne(), qui est une méthode d'instance. De plus, WaitHandle a trois autres méthodes

statiques pour la synchronisation. :

Dépendance du thread

Mutex, comme Monitor, a une dépendance au thread Nous l'avons déjà mentionné, seuls les threads qui ont obtenu le verrou

objet
    via Monitor.Enter()/TryEnter() peuvent appeler Pulse()/Wait(). /Exit(); de même, seuls les threads qui obtiennent la propriété Mutex peuvent exécuter la méthode ReleaseMutex(), sinon une exception sera levée. C'est ce qu'on appelle la dépendance aux threads.
  • En revanche, EventWaitHandle et ses classes dérivées AutoResetEvent et ManualResetEvent sont indépendantes du thread. N'importe quel thread peut signaler à EventWaitHandle de réveiller le thread bloqué dessus.

  • Le sémaphore qui sera mentionné dans le prochain article est également indépendant des threads.

Notification d'événement

EventWaitHandle, AutoResetEvent et ManualResetEvent ont tous un « Événement » dans leurs noms, mais ceci est la même chose que le propre mécanisme d'événement de net n'a rien à voir avec cela, il n'implique aucun délégué ou aucune procédure de

gestionnaire d'événement

. Par rapport au Monitor et au Mutex que nous avons rencontrés auparavant, qui nécessitent que les threads se disputent les « verrous », nous pouvons les comprendre comme des « événements » qui nécessitent que les threads attendent. Le thread se bloque en attendant que ces événements « se produisent ». Une fois "l'événement" terminé, le thread bloqué peut continuer à fonctionner après avoir reçu le signal. Afin de coopérer avec les trois méthodes statiques SingnalAndWait()/WailAny()/WaitAll() sur WaitHandle, EventWaitHandle fournit sa propre méthode unique pour terminer et redémarrer "Event" :

bool:Set() : version anglaise MSDN : définit l'état de l'événement sur signalé, permettant à un ou plusieurs threads en attente de continuer ; Défini sur l'état terminé, permettant à un ou plusieurs threads en attente de continuer. À première vue, « signalé » et « terminaison » ne semblent pas correspondre, mais à bien y réfléchir, les deux termes ne sont en réalité pas contradictoires. Si l'événement est en cours, bien sûr, il n'y a pas de "termination", alors
    les autres
      threads doivent attendre une fois l'événement terminé, alors l'événement est "terminé", nous envoyons donc un signal pour se réveiller ; le fil d'attente, donc le statut "signal envoyé" est également raisonnable. Deux petits détails :
  1. Qu'il s'agisse de la version chinoise ou anglaise, il est mentionné que cette méthode peut faire "continuer/Procéder" "un" ou "plusieurs" threads en attente (attention pas "se réveiller") . Cette méthode est donc similaire à Monitor.Pulse() et Monitor.PulseAll() en termes de « réveil ». Quant à savoir quand il est similaire à Pulse() et quand il est similaire à PulseAll(), lisez la suite.

  2. Cette méthode a une valeur de retour booléenne : true si l'opération réussit ; sinon, false. Cependant, MSDN ne nous indique pas quand l'exécution échouera. Vous pouvez uniquement demander à un Microsoft MVP.

  • bool:Reset() : Définit l'état de l'événement sur non signalé, provoquant le blocage des threads. Définit l'état de l'événement sur non signalé, provoquant le blocage des threads. De même, nous devons comprendre que « non signalé » et « non terminé » sont la même chose. Encore une fois, il existe toujours une valeur de retour absurde. La fonction de Reset() équivaut à rendre à nouveau l'événement "en cours", puis tous les threads de l'événement WaitOne()/WaitAll()/WaitAny()/SignalAndWait() seront à nouveau bloqués.

  • Constructeur

    Jetons un coup d'œil au constructeur le plus courant de EventWaitHandle Simple :

    • EventWaitHandle (Boolean initialState, mode EventResetMode) : initialise une nouvelle instance de la classe EventWaitHandle et spécifie si le handle d'attente est initialement dans un état terminé et s'il est réinitialiser automatiquement ou réinitialiser manuellement. La plupart du temps, nous utiliserons false dans le premier paramètre afin que la nouvelle instance passe par défaut à l'état "non terminé". Le deuxième paramètre EventResetMode est une énumération avec un total de deux valeurs :

    1. EventResetMode.AutoReset : Lorsque Set() est appelé, l'EventWaitHandle actuel est transféré vers À l'état terminé, s'il y a un thread bloqué sur le EventWaitHandle actuel, alors après avoir libéré un thread, le EventWaitHandle sera automatiquement réinitialisé (équivalent à appeler automatiquement Reset()) et transféré vers le non- l'état terminé à nouveau, et les threads bloqués restants (le cas échéant) continueront à se bloquer. Si aucun thread n'est bloqué après l'appel de Set(), alors EventWaitHandle restera dans l'état "terminé" jusqu'à ce qu'un thread essaie d'attendre l'événement. Après cela, EventWaitHandle sera automatiquement réinitialisé et bloqué. tous les sujets après ça.

    2. EventResetMode.ManualReset : Une fois terminé, EventWaitHandle libère tous les threads en attente avant la réinitialisation manuelle, c'est-à-dire Reset(). Il reste terminé jusqu'à ce que appelé.

    OK, maintenant nous pouvons clairement savoir quand Set() est similaire à Monitor.Pulse()/PulseAll() respectivement :

    • Lorsque EventWaitHandle fonctionne en mode AutoReset, Set() est similaire à Monitor.Pulse() en termes de fonction de réveil. Pour le moment, Set() ne peut réveiller qu’un des nombreux threads bloqués (s’il y en a plusieurs). Mais il y a quand même quelques différences entre les deux :

    1. La fonction de Set() n'est pas seulement de "réveiller" mais de "libérer", permettant au fil de continuer travailler (continuer) ; au contraire, le thread réveillé par Pulse() ne fait que rentrer dans l'état Running et participe à la compétition pour le verrouillage de l'objet. Personne ne peut garantir qu'il obtiendra le verrouillage de l'objet.

    2. L'état appelé de Pulse() ne sera pas maintenu. Par conséquent, si Pulse() est appelé alors qu'il n'y a aucun thread en attente, le prochain thread qui appelle Monitor.Wait() sera toujours bloqué, comme si Pulse() n'avait jamais été appelé. En d’autres termes, Monitor.Pulse() ne prend effet que lorsqu’il est appelé, contrairement à Set(), qui continuera jusqu’au prochain WaitXXX().

  • Lorsque la méthode Set() d'un EventWaitHandle fonctionnant en mode ManualReset est appelée, sa fonction de réveil est similaire à Monitor.PulseAll(). Tous les threads sont bloqués. recevez le signal et soyez réveillé. La différence entre les deux est exactement la même que ci-dessus.

  • Jetons un coup d'œil aux autres constructeurs de EventWaitHandle :

    • EventWaitHandle(Boolean initialState, EventResetMode mode, String name) : Nous avons déjà vu les deux premiers paramètres, et le nom du troisième paramètre est utilisé pour spécifier les événements de synchronisation à l'échelle du système nom. Oui, comme nous l'avons mentionné dans l'article Mutex, puisque la classe parent WaitHandle a la capacité de traverser des domaines de processus, comme Mutex, nous pouvons créer un EventWaitHandle global et l'utiliser plus tard pour les notifications inter-processus. Notez que le nom est toujours sensible à la casse et qu'il existe toujours des problèmes de préfixe de nom. Vous pouvez vous y référer. Cela équivaut à créer un EventWaitHandle local et sans nom lorsque le nom est null ou string vide. Toujours pareil, il est possible qu'une seule instance soit renvoyée pour représenter l'EventWaitHandle portant le même nom car il existe déjà un EventWaitHandle portant le même nom dans le système. Donc au final, toujours pareil, si vous avez besoin de savoir si cet EventWaitHandle a été créé par vous en premier, vous devez utiliser l'un des deux constructeurs suivants.

    • EventWaitHandle(Boolean initialState, EventResetMode mode, String name, out BooleancreatedNew) : CreatedNew est utilisé pour indiquer si l'EventWaitHandle a été créé avec succès, true indique le succès , false Indique qu'un événement portant le même nom existe déjà.

    • EventWaitHandle(Boolean initialState, EventResetMode mode, String name, out BooleancreatedNew, EventWaitHandleSecurity) : concernant les problèmes de sécurité, veuillez vérifier directement l'exemple sur ce constructeur. Les problèmes de sécurité de MutexEventWaitHandle global doivent faire l'objet d'une plus grande attention que ceux de Mutex, car il est possible que des pirates utilisent le même nom d'événement pour envoyer des signaux ou organiser vos threads, ce qui peut sérieusement nuire à votre logique métier.

    Démo MSDN


    using System;using System.Threading;public class Example
    {    // The EventWaitHandle used to demonstrate the difference    // between AutoReset and ManualReset synchronization events.    //    private static EventWaitHandle ewh;    // A counter to make sure all threads are started and    // blocked before any are released. A Long is used to show    // the use of the 64-bit Interlocked methods.    //    private static long threadCount = 0;    // An AutoReset event that allows the main thread to block    // until an exiting thread has decremented the count.    //    private static EventWaitHandle clearCount = 
            new EventWaitHandle(false, EventResetMode.AutoReset);
    
        [MTAThread]    public static void Main()
        {        // Create an AutoReset EventWaitHandle.        //        ewh = new EventWaitHandle(false, EventResetMode.AutoReset);        // Create and start five numbered threads. Use the        // ParameterizedThreadStart delegate, so the thread        // number can be passed as an argument to the Start 
            // method.
            for (int i = 0; i <= 4; i++)
            {
                Thread t = new Thread(                new ParameterizedThreadStart(ThreadProc)
                );
                t.Start(i);
            }        // Wait until all the threads have started and blocked.        // When multiple threads use a 64-bit value on a 32-bit        // system, you must access the value through the        // Interlocked class to guarantee thread safety.        //        while (Interlocked.Read(ref threadCount) < 5)
            {
                Thread.Sleep(500);
            }        // Release one thread each time the user presses ENTER,        // until all threads have been released.        //        while (Interlocked.Read(ref threadCount) > 0)
            {
                Console.WriteLine("Press ENTER to release a waiting thread.");
                Console.ReadLine();            // SignalAndWait signals the EventWaitHandle, which            // releases exactly one thread before resetting, 
                // because it was created with AutoReset mode. 
                // SignalAndWait then blocks on clearCount, to 
                // allow the signaled thread to decrement the count            // before looping again.            //            WaitHandle.SignalAndWait(ewh, clearCount);
            }
            Console.WriteLine();        // Create a ManualReset EventWaitHandle.        //        ewh = new EventWaitHandle(false, EventResetMode.ManualReset);        // Create and start five more numbered threads.        //        for(int i=0; i<=4; i++)
            {
                Thread t = new Thread(                new ParameterizedThreadStart(ThreadProc)
                );
                t.Start(i);
            }        // Wait until all the threads have started and blocked.        //        while (Interlocked.Read(ref threadCount) < 5)
            {
                Thread.Sleep(500);
            }        // Because the EventWaitHandle was created with        // ManualReset mode, signaling it releases all the        // waiting threads.        //        Console.WriteLine("Press ENTER to release the waiting threads.");
            Console.ReadLine();
            ewh.Set();
    
        }    public static void ThreadProc(object data)
        {        int index = (int) data;
    
            Console.WriteLine("Thread {0} blocks.", data);        // Increment the count of blocked threads.
            Interlocked.Increment(ref threadCount);        // Wait on the EventWaitHandle.        ewh.WaitOne();
    
            Console.WriteLine("Thread {0} exits.", data);        // Decrement the count of blocked threads.
            Interlocked.Decrement(ref threadCount);        // After signaling ewh, the main thread blocks on        // clearCount until the signaled thread has 
            // decremented the count. Signal it now.        //        clearCount.Set();
        }
    }
    Copier après la connexion


    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Déclaration de ce site Web
    Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

    Outils d'IA chauds

    Undresser.AI Undress

    Undresser.AI Undress

    Application basée sur l'IA pour créer des photos de nu réalistes

    AI Clothes Remover

    AI Clothes Remover

    Outil d'IA en ligne pour supprimer les vêtements des photos.

    Undress AI Tool

    Undress AI Tool

    Images de déshabillage gratuites

    Clothoff.io

    Clothoff.io

    Dissolvant de vêtements AI

    AI Hentai Generator

    AI Hentai Generator

    Générez AI Hentai gratuitement.

    Outils chauds

    Bloc-notes++7.3.1

    Bloc-notes++7.3.1

    Éditeur de code facile à utiliser et gratuit

    SublimeText3 version chinoise

    SublimeText3 version chinoise

    Version chinoise, très simple à utiliser

    Envoyer Studio 13.0.1

    Envoyer Studio 13.0.1

    Puissant environnement de développement intégré PHP

    Dreamweaver CS6

    Dreamweaver CS6

    Outils de développement Web visuel

    SublimeText3 version Mac

    SublimeText3 version Mac

    Logiciel d'édition de code au niveau de Dieu (SublimeText3)

    Comment gérer les caractères spéciaux dans la langue C Comment gérer les caractères spéciaux dans la langue C Apr 03, 2025 pm 03:18 PM

    Dans le langage C, les caractères spéciaux sont traités à travers des séquences d'échappement, telles que: \ n représente les pauses de ligne. \ t signifie le caractère d'onglet. Utilisez des séquences d'échappement ou des constantes de caractères pour représenter des caractères spéciaux, tels que char c = '\ n'. Notez que l'arrière-plan doit être échappé deux fois. Différentes plates-formes et compilateurs peuvent avoir différentes séquences d'échappement, veuillez consulter la documentation.

    Quel est le rôle de char dans les chaînes C Quel est le rôle de char dans les chaînes C Apr 03, 2025 pm 03:15 PM

    En C, le type de char est utilisé dans les chaînes: 1. Stockez un seul caractère; 2. Utilisez un tableau pour représenter une chaîne et se terminer avec un terminateur nul; 3. Faire fonctionner via une fonction de fonctionnement de chaîne; 4. Lisez ou sortant une chaîne du clavier.

    La différence entre char et wchar_t dans le langage C La différence entre char et wchar_t dans le langage C Apr 03, 2025 pm 03:09 PM

    Dans le langage C, la principale différence entre Char et WCHAR_T est le codage des caractères: Char utilise ASCII ou étend ASCII, WCHAR_T utilise Unicode; Char prend 1 à 2 octets, WCHAR_T occupe 2-4 octets; Char convient au texte anglais, WCHAR_T convient au texte multilingue; Le char est largement pris en charge, WCHAR_T dépend de la prise en charge du compilateur et du système d'exploitation Unicode; Le char est limité dans la gamme de caractères, WCHAR_T a une gamme de caractères plus grande et des fonctions spéciales sont utilisées pour les opérations arithmétiques.

    Comment utiliser divers symboles dans le langage C Comment utiliser divers symboles dans le langage C Apr 03, 2025 pm 04:48 PM

    Les méthodes d'utilisation des symboles dans la couverture du langage C Couverture arithmétique, l'affectation, les conditions, la logique, les opérateurs de bits, etc. Les opérateurs arithmétiques sont utilisés pour les opérations mathématiques de base, les opérateurs d'affectation sont utilisés pour les opérations et les opérations de la soustraction, la multiplication et les opérations de division, les opérations BIT sont utilisé pointeurs nuls, marqueurs de fin de fichier et valeurs non nucères.

    La différence entre le multithreading et le C # asynchrone La différence entre le multithreading et le C # asynchrone Apr 03, 2025 pm 02:57 PM

    La différence entre le multithreading et l'asynchrone est que le multithreading exécute plusieurs threads en même temps, tandis que les opérations effectuent de manière asynchrone sans bloquer le thread actuel. Le multithreading est utilisé pour les tâches à forte intensité de calcul, tandis que de manière asynchrone est utilisée pour l'interaction utilisateur. L'avantage du multi-threading est d'améliorer les performances informatiques, tandis que l'avantage des asynchrones est de ne pas bloquer les threads d'interface utilisateur. Le choix du multithreading ou asynchrone dépend de la nature de la tâche: les tâches à forte intensité de calcul utilisent le multithreading, les tâches qui interagissent avec les ressources externes et doivent maintenir la réactivité de l'interface utilisateur à utiliser asynchrone.

    Comment convertir le charbon dans la langue C Comment convertir le charbon dans la langue C Apr 03, 2025 pm 03:21 PM

    Dans le langage C, la conversion de type char peut être directement convertie en un autre type par: Casting: Utilisation de caractères de casting. Conversion de type automatique: Lorsqu'un type de données peut accueillir un autre type de valeur, le compilateur le convertit automatiquement.

    Quelle est la fonction de la somme du langage C? Quelle est la fonction de la somme du langage C? Apr 03, 2025 pm 02:21 PM

    Il n'y a pas de fonction de somme intégrée dans le langage C, il doit donc être écrit par vous-même. La somme peut être obtenue en traversant le tableau et en accumulant des éléments: Version de boucle: la somme est calculée à l'aide de la longueur de boucle et du tableau. Version du pointeur: Utilisez des pointeurs pour pointer des éléments de tableau, et un résumé efficace est réalisé grâce à des pointeurs d'auto-incitation. Allouer dynamiquement la version du tableau: allouer dynamiquement les tableaux et gérer la mémoire vous-même, en veillant à ce que la mémoire allouée soit libérée pour empêcher les fuites de mémoire.

    Comment utiliser Char Array dans la langue C Comment utiliser Char Array dans la langue C Apr 03, 2025 pm 03:24 PM

    Le Array Char stocke des séquences de caractères en C et est déclaré Char Array_name [Taille]. L'élément d'accès est passé par l'opérateur d'indice, et l'élément se termine par le terminateur nul «\ 0», qui représente le point final de la chaîne. Le langage C fournit une variété de fonctions de manipulation de cordes, telles que strlen (), strcpy (), strcat () et strcmp ().

    See all articles