Rails

Lorsqu’on fait du multithreading, il arrive qu’on veuille contrôler le flux d’exécution de nos threads. Un thread peut par exemple, attendre le signal d’un autre pour continuer un traitement. L’un des outils les plus simples pour y parvenir est la classe ManualResetEvent. Voyons comment elle fonctionne.

Création d’un ManualResetEvent

Les scénarios où un thread doit en attendre un autre pour continuer son exécution sont monnaie courante lorsqu’on fait du multithreading. Le fonctionnement de ManualResetEvent est très simple. Les threads se mettent en attente en appelant la méthode WaitOne(). Celle-ci bloque leur exécution jusqu’à ce qu’un autre thread appelle la méthode Set(). Cette méthode leur envoie le signal qu’ils attendent pour continuer exécution.

La création d’une instance de ManualResetEvent est très simple.

var  mre = new ManualResetEvent (bool);

Le constructeur prend en paramètre un booléen. Si bool = false, les threads en attente ne poursuivront leur exécution que si l’on appelle Set(). Si bool = true, ils continueront leur exécution même si Set() n’est pas appelée.

Voyons un exemple:

ManualResetEvent manualResetEvent = new ManualResetEvent(false);

new TaskFactory().StartNew(() =>
    {

            Console.WriteLine("waiting for signal");
            manualResetEvent.WaitOne();
            Console.WriteLine("signal obtained");
        
    });

Thread.Sleep(5000);

Vu qu’on a initialisé notre ManualResetEvent avec false, l’appel à WaitOne() attendra l’ouverture du signal avec un appel à Set() avant de continuer.
Notre code n’appelle jamais Set() donc la ligne Console.WriteLine(« signal obtained ») n’est jamais exécutée.

Elle sera exécutée si on initialise le ManualResetEvent avec true.

ManualResetEvent manualResetEvent = new ManualResetEvent(true);

Dans ce cas, l’appel à WaitOne() ne bloquera pas l’exécution du thread.

WaitOne

Comme vue ci-dessus, WaitOne() bloque notre thread. Celui-ci ne continuera son exécution qu’à la réception d’un signal d’un autre thread.

Il existe une autre version de cette méthode qui prend en paramètre une durée en millisecondes. Une fois le temps expiré, notre thread poursuit son exécution.

Set

Set() envoie le signal qui permet aux threads en attente de continuer leur exécution.

Reset

Reset() permet de réinitialiser notre manualResetEvent lorsqu’on a déjà appelé Set(). Après son exécution, les threads qui exécuterons WaitOne() seront de nouveau en attente.

ManualResetEvent – Exemple

Dans l’exemple ci-dessous, notre thread ne continue son exécution que lorsque l’utilisateur entre la lettre ‘y’ dans la console.

ManualResetEvent manualResetEvent = new ManualResetEvent(false);

new TaskFactory().StartNew(() =>
{

    Console.WriteLine("waiting for signal");
    manualResetEvent.WaitOne();
    Console.WriteLine("signal obtained");

});
Thread.Sleep(1000);


Console.WriteLine("Press  y to continue ");

string s = Console.ReadLine();

if (s == "y") manualResetEvent.Set();

Thread.Sleep(2000);

En conclusion, la classe ManualResetEvent en C# est un outil puissant pour synchroniser les threads et éviter les problèmes de concurrence. Elle facilité le contrôle du flux d’exécution des threads en permettant à un thread d’attendre qu’un autre ait terminé une opération critique pour poursuivre son exécution.

Auteur : Daniel MINKO FASSINOU

Laisser un commentaire




Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.