Synchronisation de threads en C#

Synchronisation de threads en C# - C#/.NET managed - Programmation

Marsh Posté le 28-06-2004 à 09:33:53    

Bonjour,
 
j'ai une petite question assez classique.
en C#, je dispose d'une classe qui, dans son main, lance un thread qui fait un traitement a intervalle regulier.
 
static void Main(string[] args)
{
maClasse wss = new maClasse();
// demarre le thread  
wss.StartProcess();
}
 
je ne sais malheureusement pas comment stopper le thread ainsi lancé.
en effet, après quelques essais, je me suis rendu compte que le thread n'etait jamais arrete (ce qui dans l'absolu me semble assez normal).
 
ma question est donc :  
 
savez-vous comment arreter ce thread de maniere propre ?
 
v.

Reply

Marsh Posté le 28-06-2004 à 09:33:53   

Reply

Marsh Posté le 28-06-2004 à 09:35:33    

oui, y a des primitives pour, mais ça n'est pas vraiment propre. A toi de faire en sorte que ton thread s'arrete tout seul, .Join() le pour attendre sa fin

Reply

Marsh Posté le 28-06-2004 à 09:44:09    

Taz a écrit :

oui, y a des primitives pour, mais ça n'est pas vraiment propre. A toi de faire en sorte que ton thread s'arrete tout seul, .Join() le pour attendre sa fin


 
ok merci pour ta reponse, je vais jeter un coup d'oeil a Join
 
v.

Reply

Marsh Posté le 28-06-2004 à 09:44:12    

Code :
  1. using System.Threading;
  2. public class ThreadKiller
  3. {
  4.   public static void Go()
  5.   {
  6.     try
  7.       {
  8.         while(true)
  9.         {
  10.           System.Console.WriteLine("Plop" );
  11.           Thread.Sleep(1000);
  12.         }
  13.       }
  14.     catch(ThreadAbortException e)
  15.       {
  16.         System.Console.WriteLine("Ouch {0}", e);
  17.       }
  18.   }
  19.   public static void Main()
  20.   {
  21.     Thread t = new Thread( new ThreadStart(Go) );
  22.     t.Start();
  23.     Thread.Sleep(3000);
  24.     t.Abort();
  25.   }
  26. }


Reply

Marsh Posté le 28-06-2004 à 09:47:29    

merci pour le bout de code, c'est effectivement ce que j'ai fait.
 
mon probleme est un peu different (et je doute qu'il y ait une solution ideale).
 
dans mon main, je lance un thread qui fait une action qui ne se terminera jamais (il boucle et envoit de l'info).
 
par contre, il se peut que j'aie envie de l'arreter mais apres la fin du main.
 
je ne suis meme pas sur que ca soit realisable.
 
v.

Reply

Marsh Posté le 28-06-2004 à 09:49:34    

il se passe rien après la fin du Main :o
 
le problème, il est dans ta tête

Reply

Marsh Posté le 28-06-2004 à 09:55:30    

Taz a écrit :

il se passe rien après la fin du Main :o
 
le problème, il est dans ta tête


 
le thread que j'ai lance tourne toujours non ?
meme apres la fin du main ?
 
donc ma tete ne va pas si mal que ca !!!  :o  
 
v.

Reply

Marsh Posté le 28-06-2004 à 09:56:17    

vonm a écrit :


par contre, il se peut que j'aie envie de l'arreter mais apres la fin du main.

[:heink]


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 28-06-2004 à 09:56:56    

vonm a écrit :

le thread que j'ai lance tourne toujours non ?
meme apres la fin du main ?
 
donc ma tete ne va pas si mal que ca !!!  :o  
 
v.


euh, la fin du main signifie la fin du programme et de tous les threads associés hein


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 28-06-2004 à 09:58:46    

Harkonnen a écrit :

euh, la fin du main signifie la fin du programme et de tous les threads associés hein


 
ben la y'a un truc qui m'echappe parce que ce n'est absolument pas le comportement que je constate.
 
je comprends pas parce que le thread qui est lance continue alors que je n'ai pas de Join avant la fin de mon main.
 
est-il possible qu'il en fasse un automatiquement ?
 
v.

Reply

Marsh Posté le 28-06-2004 à 09:58:46   

Reply

Marsh Posté le 28-06-2004 à 10:07:18    

vonm a écrit :

ben la y'a un truc qui m'echappe parce que ce n'est absolument pas le comportement que je constate.
 
je comprends pas parce que le thread qui est lance continue alors que je n'ai pas de Join avant la fin de mon main.
 
est-il possible qu'il en fasse un automatiquement ?
 
v.


 
je viens de voir qu'il existe des notions de threads forground et threads background.
peut-etre que mon probleme vient de la, je regarde.
 
merci pour votre aide
 
v.

Reply

Marsh Posté le 28-06-2004 à 10:23:55    

les notions ça va te mener loin...

Reply

Marsh Posté le 28-06-2004 à 10:35:01    

Taz a écrit :

les notions ça va te mener loin...


 
oh mais merde !
 
ecoute Taz, t'es bien gentil, tu as essayé de m'aider mais je supporte difficilement ton air supérieur et pédant.
 
donc, je pense qu'on peut arrêter la, je vais me debrouiller autrement.
 
v.

Reply

Marsh Posté le 28-06-2004 à 10:39:21    

tu ferais bien de lire toute la documentation de Thread au lieu de t'énerver, ça te donnera un aperçu de ce que tu peux faire. Après tout ce qui concerne System.Threading.
 
Mais on a bien compris que tu bricolais jusqu'à que ça marche à peu près

Reply

Marsh Posté le 28-06-2004 à 10:43:33    

Taz a écrit :

tu ferais bien de lire toute la documentation de Thread au lieu de t'énerver, ça te donnera un aperçu de ce que tu peux faire. Après tout ce qui concerne System.Threading.
 
Mais on a bien compris que tu bricolais jusqu'à que ça marche à peu près


 
oui, tu as raison.
merci pour ton aide precieuse.
 
le sujet est clos.
 
v.

Reply

Marsh Posté le 28-06-2004 à 13:48:11    

En ce qui concerne le code donné par Taz.
Je préfère faire autrement : pour controller l'arret/la pause d'un thread, il vaut mieux utiliser de bons vieux boolean, tout simples, qui effectue l'action ou non.
Un ex :
 
using System.Threading;  
   
  public class ThreadKiller  
  {  
      protected bool actif,pause;
      public static void Go()  
      {  
          try  
            {  
                while(actif)  
                {  
                    if (!pause) System.Console.WriteLine("Plop" );  
                    Thread.Sleep(1000);  
                }  
            }  
          catch(ThreadAbortException e)  
            {  
                System.Console.WriteLine("Ouch {0}", e);  
            }  
      }  
     
      public static void Main()  
      {  
          actif=true;
          pause=false;
          Thread t = new Thread( new ThreadStart(Go) );  
          t.Start();
          actif=false;
      }  
  }
 
Quand actif=false, le thread se termine tout simplement et on en entend plus parler.
Le thread.abort est viable, mais c'est moins beau. Attention, croire que le thread s'arrète immédiatement apres l'appel à abort() est faux, le système n'arrete le thread qu'un peu plus tard (quand il est en pause je crois), ce qui revient grosso-modo à la solution que j'ai donné, en moins clair.
 
Sinon, il faut à tout prix éviter l'emploi des primitives stop(), resume() et compagnie... Si on se trompe (ex : on fait 2 resume d'affilé sur le meme thread), on a droit à une belle exception, qu'il faut donc catcher ... et ca fout la merde dans le source pour rien.
 
Bref, le boolean, ya que ca de vrai :)
 
EDIT : pause=false au début, c'est mieux :)


Message édité par oliv5 le 28-06-2004 à 13:49:04
Reply

Marsh Posté le 28-06-2004 à 15:12:28    

non, c'est une mauvaise approche. déjà il faudrait utiliser un événement et pas un booléen

Reply

Marsh Posté le 28-06-2004 à 16:32:28    

du genre ? J'ai beau chercher, je vois pas ce que les évènements viennent faire ici.  :??:  
Mais bon, je suis ptetre pas dans le coup là, je fais plus ca à longueur de journée  :D  
 
Au passage, cette approche marche trés bien, tout comme la tienne certes, mais présente l'avantage d'etre plus claire. Qui plus est, j'ai déjà vu de nombreux sources de Petzol (ie une brute du win32) procéder de meme.
 
Ps : pardon pour l'othographe du nom de ce Monsieur dont je ne me rapelle plus :D


Message édité par oliv5 le 28-06-2004 à 16:37:13
Reply

Marsh Posté le 28-06-2004 à 16:51:00    

Ha, on me fait signe au bureau d'en face que l'emploi du abort est désastreux :)
 
explication : tu ne sais pas ou en est ton thread quand il est aborté, ie, tu ne controle pas le nettoyage éventuel des objets/tableaux/listes dont tu te sert.
 
Ce qui apporte de l'eau à mon moulin : avec un ptit boolean, tu sais par où passe ton thread.
 
Sinon, on peut rajouter à mon bout de code des get-set pour faire plus propre, mettre les boolean en private (plus sur).

Reply

Marsh Posté le 28-06-2004 à 16:55:22    

le abort est pas désastreux en C#, à toi de bien rattraper l'exception. mais ça peut devenir long à gérer. et il faut utiliser des événements avec ton attente, ton thread bien qu'endormi est ininterruptible. utilise les événements. je viens de comprendre. Allo la moule, on parle de synchronisation, de //, pas des event C# !
 
et les get/set en C#, ça pue.

Reply

Marsh Posté le 28-06-2004 à 17:02:27    

Taz a écrit :

le abort est pas désastreux en C#, à toi de bien rattraper l'exception. mais ça peut devenir long à gérer. et il faut utiliser des événements avec ton attente, ton thread bien qu'endormi est ininterruptible. utilise les événements. je viens de comprendre. Allo la moule, on parle de synchronisation, de //, pas des event C# !
 
et les get/set en C#, ça pue.


 
putain mais c'est pas vrai, t'es en guerre contre le reste de l'humanité ou quoi ???
 
tu sais pas repondre correctement, sans te foutre de la gueule des gens ???
 
si un sujet te fait chier ou ne t'interesse pas, ben tu laisses tomber !
 
ah et tu peux me preciser aussi en quoi les get/set de C# sont puants ?
 
Edit : pour info au sujet de la methode Abort(), les gens qui travaillent au framework SDF d'opennetcf.org ont cree une classe adaptateur de la classe Thread. L'appel a la methode Abort() de cette classe renvoit une BestPracticeViolationException (c'est dire l'interet de la methode !!!) . Etant donne que je fais beaucoup plus confiance a ces mecs la (qui je le rappelle travaillent tous sur le framework dotnet chez MS) qu'a toi, je crois que je vais privilegier la methode d'oliv5.
http://www.opennetcf.org/library/O [...] Abort.html
 
v.


Message édité par vonm le 28-06-2004 à 17:10:18
Reply

Marsh Posté le 28-06-2004 à 17:51:18    

c'est toi qui t'excites. les propriétés, ça te dit quelque chose ? quand à ce que font les autres, c'est leur problème. le Abort ne pose problème qui si on ne le controle pas. T'as quad demander à ces gens de t'expliquer ce qu'est événement, on verra qui est le plus sympa

Reply

Marsh Posté le 28-06-2004 à 18:31:46    

Taz a écrit :

c'est toi qui t'excites. les propriétés, ça te dit quelque chose ? quand à ce que font les autres, c'est leur problème. le Abort ne pose problème qui si on ne le controle pas. T'as quad demander à ces gens de t'expliquer ce qu'est événement, on verra qui est le plus sympa


 
je m'excite pas du tout, au contraire je suis en general un animal particulierement placide.
j'ai juste un peu de mal avec ta maniere de repondre a tout le monde.
 
pour te repondre, oui, je sais ce que sont les proprietes, mais tu n'as pas repondu a ma question ni justifié ta remarque (je cite "les get/set en C#, ça pue" ).
 
quant a ta derniere trouvaille :
 

Citation :

T'as quad demander à ces gens de t'expliquer ce qu'est événement, on verra qui est le plus sympa


 
je ne vais certainement pas deranger les gens en question pour ca. par contre, je suis un eleve particulierement attentif et interesse, j'attends donc de toi que tu m'expliques cela afin que je puisse me rendre compte de la qualite de ton argumentaire.
 
par contre, je te previens tout de suite des trucs tels que "ca pue" ou "t'as qu'a leur demander" ne me paraissent pas des explications valables, va falloir argumenter un peu plus que ca...
 
v.

Reply

Marsh Posté le 28-06-2004 à 20:54:50    

- le C# ne s'est pas doté de propriété pour qu'on écrive des get/set.
- les événements, tu trouveras ça au même chapitre que les mutex, sémaphores, barrière et condition

Reply

Marsh Posté le 28-06-2004 à 23:30:05    

Taz a écrit :

- le C# ne s'est pas doté de propriété pour qu'on écrive des get/set.
- les événements, tu trouveras ça au même chapitre que les mutex, sémaphores, barrière et condition


 
les proprietes sont fait de la meme facon que les get-set, d'ailleurs c'est quasiment équivalent. Je prefere les get-set personnellement, mais c'est kifkif. Pour moi, c'est plus clair c'est tout, car c'est utilisé dans d'autres langages, donc mon code reste uniforme et plus facile a traduire. Je me rapelle avoir passé tout mon jeu de pong en réseau du java vers le C# tres facilement, car, entre autre, il etait bourré de get-set.
 
Pour ce qui est des evenements, parlons plutot d'event, car c'est le terme anglais qui est utilisé dans les noms des fonctions  :D  
Je vois de quoi tu parles, et tu as raison, ca permet bien de faire de la synchro de thread.  
Mais en fait, le pb n'est pas là, contrairement a ce que le sujet du topic laiserais supposer, le pb n'est pas de synchroniser 2 threads, mais d'arréter 1 thread :)
=> D'ou notre petite prise de bec : mon bout de code ne fait pas de synchronisation, il permet juste de controller 1 thread dans sa pause et son arret.  :sol:  
=> D'ou la justesse de ta remarque : les "event" permettent de synchroniser 2 threads, au meme titre que les mutex et les sémaphores.  :jap:  
 
=> tu as mal lu mon code et la première question de vonm :)

Reply

Marsh Posté le 28-06-2004 à 23:34:00    

controller un thread, c'est de la synchronisation. Et je dis événement, je m'en fout du terme anglais. Et ton code je l'ai bien lu, il faut utiliser un événement et pas un booléen, je maintiens

Reply

Marsh Posté le 29-06-2004 à 08:49:25    

Taz a écrit :

controller un thread, c'est de la synchronisation. Et je dis événement, je m'en fout du terme anglais. Et ton code je l'ai bien lu, il faut utiliser un événement et pas un booléen, je maintiens


 
ca me surprend un peu car si ma memoire est bonne, en java, l'arret de thread passe par un booleen.  
Maintenant, le parallele avec java n'est peut etre pas indique dans ce cas la.
envoie un exemple, peut-etre qu'on comprendra.
 
Edit: effectivement oliv5, tu as bien saisi de quoi je voulais parler.
 
v.


Message édité par vonm le 29-06-2004 à 08:50:30
Reply

Marsh Posté le 29-06-2004 à 09:50:44    

Taz a écrit :

controller un thread, c'est de la synchronisation. Et je dis événement, je m'en fout du terme anglais. Et ton code je l'ai bien lu, il faut utiliser un événement et pas un booléen, je maintiens


 
Ben moi, je maintiens que l'arret définitif d'un thread ne se fait pas par un mutex/semaphore. Ici il n'y a qu'un thread et le boolean actif permet bien de l'arreter.
 
Note : vnomn veut arréter définitivement son thread, c'est ca sa question si j'ai bien compris.
 
Sinon, pour mettre en pause un thread, oui, la meilleur solution est le mutex. Encore que ... si ton mutex est actif, et ton thread bloqué, tu peux toujours courir pour que le abort() arrete ton thread => l'arret ne se produit que si ton thread est vivant, d'où l'interet d'une solution simple comme la mienne, pour de petites applis : meme si en pause, le thread est vivant donc l'arret a bien lieu (avec abort() ou avec un boolean)
 
Mais là n'est pas la question.
La question est : je veux arréter définitivement mon thread.
=> boolean dans le while


Message édité par oliv5 le 29-06-2004 à 09:51:35
Reply

Marsh Posté le 29-06-2004 à 11:31:06    

bon écoute, tu ferais bien de regarder AutoResetEvent et ManualResetEvent.
 
un boucle
 
tant que <test>:
  travail
  attente
 
fin thread
 
doit toujours se traduire par un événement. t'en fais ce que tu veux. bricoles avec tes booléens sinon

Reply

Marsh Posté le 29-06-2004 à 13:40:07    

Taz a écrit :

bon écoute, tu ferais bien de regarder AutoResetEvent et ManualResetEvent.
 
un boucle
 
tant que <test>:
  travail
  attente
 
fin thread
 
doit toujours se traduire par un événement. t'en fais ce que tu veux. bricoles avec tes booléens sinon


 
Je sens que tu perds ton sang-froid :pt1cable:  
Merci, mais je sais ce que c'est ces putains de resetEvent!!!
 
tant que test => c'est exactement ce que j'ai proposé.
travail, rien a redire
attente : sleep
fin thread
 
Je ne vois pas ou tu fous ton putain de ManualResetEventou ton AutoResetEvent.
Je veux bien un exemple complet car je vois vraiment pas. Je suis sur qu'en ecrivant l'exemple tu verras que ca ne te sert pas, dans notre cas.
Puisque tu as une solution magique, je la veux.

Reply

Marsh Posté le 29-06-2004 à 13:55:44    

c'est pas comme si ça faisait depuis le début du topic je te disais de lire la documentation. Tu ne sais même pas ce qu'est un événement, alors ne dis pas que c'est nul, ou inapproprié.

Reply

Marsh Posté le 29-06-2004 à 14:09:35    

Taz a écrit :

c'est pas comme si ça faisait depuis le début du topic je te disais de lire la documentation. Tu ne sais même pas ce qu'est un événement, alors ne dis pas que c'est nul, ou inapproprié.


 
personne n'a dit que c'etait nul.
inapproprie oui, mais certainement qu'un exemple va nous convaincre...
 
on est deux a t'en demander un maintenant !
 
v.

Reply

Marsh Posté le 29-06-2004 à 14:11:48    

vonm a écrit :


on est deux a t'en demander un maintenant !


3 :o
pas pour mettre Taz à l'épreuve, mais par simple curiosité ;)


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 29-06-2004 à 14:18:15    

non mais personne sait ce que c'est qu'un événement ?

Reply

Marsh Posté le 29-06-2004 à 14:25:48    

Taz a écrit :

non mais personne sait ce que c'est qu'un événement ?


 
mais puisque je te dit que je sais ce que c'est les manuelResetEvent et le AutoResetEvent !!!!
Je ne vois juste absolument pas en quoi ils permettent de resoudre notre problème, qui est, je le rapelle, d'arréter définitivement un thread (et pas le bloquer simplemement !!! l'arréter, fini, nada, plus rien)
 
 

Citation :

pas pour mettre Taz à l'épreuve, mais par simple curiosité ;)


 
Bah moi, si, dsl, mais quand je vois qqu'un d'aussi catégorique et que je suis certain qu'il a tort, soit il a raison et je suis naze, soit il a tord. Personnellement, je m'en fous, j'aimerais bien apprendre un truc aujourd'hui et allait améliorer mes vieilles applis.
Donc j'aimerais bien un exemple, qui resolve le problème du jour (et pas un autre) car je sais comment on se sert des event pour synchroniser 2 threads, mais là n'est pas le problème.

Reply

Marsh Posté le 29-06-2004 à 14:30:31    

parce que pendant que ton thread dort il est ininterruptible putain, ça saute aux yeux ! dans ce genre de cas, on a souvent des thread qui dorment plusieurs dizaines de secondes, ton booléen, i va être vachement apprécié, il va falloir qu'une itération de complète de la boucle se termine avant de pouvoir finir le thread.


Message édité par Taz le 29-06-2004 à 14:33:27
Reply

Marsh Posté le 29-06-2004 à 15:04:27    

l'exemple de MS est bien
 
sinon, genre ça

Code :
  1. using System.Threading;
  2. public class Evenement
  3. {
  4.   ManualResetEvent stop;
  5.   public Evenement()
  6.   {
  7.     this.stop = new ManualResetEvent(false);
  8.   }
  9.   public void TourneEnRond()
  10.   {
  11.     while(this.stop.WaitOne(1000, true))
  12. {
  13.   System.Console.WriteLine("Tournicoti..." );
  14. }
  15.   }
  16.   public void AntiBulle()
  17.   {
  18.     Thread.Sleep(3500);
  19.     this.stop.Set();
  20.   }
  21.   public static void Main()
  22.   {
  23.     Evenement eve = new Evenement();
  24.     Thread[] tasks = new Thread[2]
  25.       {
  26. new Thread( new ThreadStart(eve.TourneEnRond) ),
  27. new Thread( new ThreadStart(eve.AntiBulle) )
  28.       };
  29.     foreach(Thread t in tasks)
  30.     {
  31.       t.Start();
  32.     }
  33.     foreach(Thread t in tasks)
  34.     {
  35.       t.Join();
  36.     }
  37.   }
  38. }

pas testé, ma version de mono segfault, je suis entrain de mettre à jour

Reply

Marsh Posté le 29-06-2004 à 15:31:12    

Taz a écrit :

parce que pendant que ton thread dort il est ininterruptible putain, ça saute aux yeux ! dans ce genre de cas, on a souvent des thread qui dorment plusieurs dizaines de secondes, ton booléen, i va être vachement apprécié, il va falloir qu'une itération de complète de la boucle se termine avant de pouvoir finir le thread.


 
Gnnnnnn :fou:  
Et quand il est bloqué par un event, c'est pareil !!!! Ton abort ne fera rien !! L'OS ne te garantis pas quand le thread est tué !
Donc ca ne change rien !

Reply

Marsh Posté le 29-06-2004 à 15:36:13    

mais un event n'est pas bloquant si tu lui dit de ne pas l'être ... tu mélanges tout. Si ton thread ne vérifie pas de lui même s'il doit s'arrêter à intervalles réfuliers, il n'y a évidemment pas de solution. par contre, si c'est le cas, il faut utiliser un événement.

Reply

Marsh Posté le 29-06-2004 à 15:37:47    

Haaa enfin tu nous sort un bout de code.
Je testerais ca, je prefere deja ca au abort() que tu proposait.
 
(un bout de code vaut mieux qu'un discours pas clair, enervé et enervant du style "mais t'es nul tu vois pas" )

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed