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.
Laisser un commentaire