Forum Clubic

[VB.NET / C#] Communication entre threads

Salut, j’ai un leger problème avec un programme en vb.net. (mais une solution en C# me conviendrait aussi)
En gros, il y a un thread principal et un nombre variable de threads “auxiliaires”. Ces threads auxiliaires controlent periodiquement des données, et j’ai besoin que le thread principal fasse quelques actions quand des modifications sont repérées. Pour diverses raisons, il faut absolument que ce soit le thread principal qui fasse l’action et les threads auxiliaires qui controlent les données.
Je me retrouve donc confronté au problème suivant : comment, depuis un thread auxiliaire, forcer le thread principal à décrocher sur la routine appropriée, puis reprendre ce qu’il faisait ?
J’ai pensé à utiliser des exceptions personnalisées (et placer les actions à executer dans la fonction traitant lesdites exceptions) mais à ce moment là j’ai encore un autre problème : comment, depuis le thread auxiliaire, forcer le thread principal à provoquer une exception ? Bref, je tourne en rond.
Et, par souci d’économie de ressources, je souhaiterais éviter la solution qui consisterais à controler périodiquement l’état des threads auxiliaires depuis le thread principal (les modifications des données à surveiller sont trop aléatoires, il peut y avoir plusieurs modifications en quelques minutes comme il ne peut en avoir aucune en plusieurs heures).
Bref, si vous avez une idée, je suis preneur, là je seche completement.

les events… tout simplement :wink:

C’est les conditions? genre pthread_cond_t ?

Je veux bien les events, mais euh… Ca marche comment ? :slight_smile:
Je sais comment créer un handler pour les evenements, mais comment provoquer un evenement dans le thread principal depuis les threads auxiliaires ?

ça pourrait t’aider :
http://www.codeproject.com/csharp/workerthread.asp

:]

Bon, j’ai regardé en détail ce code, et j’y ai apprit deux choses :

  • les fonctions “delegate” qui permettent à un thread d’executer des fonctions auxquelles ils n’aurait normalement pas accès. C’est bon à savoir, ça me reservira, mais c’est toujours le thread qui execute la fonction, donc ça ne résoud pas mon problème.
  • les “ManualResetEvent” qui sont, si j’ai bien comprit, des sorts de mutex améliorés. Donc ça permet en effet une communication/synchronisation entre les threads, mais ça impliquerait que le thread principal se stoppe en attendant les threads auxiliaires, ce qui dans mon cas n’est pas possible.

Donc soit je n’ai pas tout comprit, soit ça ne résoud pas mon problème :slight_smile:

euh… je crois que je n’ai pas bien compris ta question ;p

>mais c’est toujours le thread qui execute la fonction, donc ça ne résoud pas mon problème.
ben non AddString est dans le thread principal… ! c’est comme si tu appelais une fonction

>mais ça impliquerait que le thread principal se stoppe en attendant les threads auxiliaires, ce qui dans mon cas n’est pas possible.
qu’est ce que tu veux dire par “se stoppe” ?! :heink:

Si créé une fonction qui affiche le nom du thread en cours, que j’en fais une delegate, et que je la fait executer par le thread auxiliaire, c’est toujours le nom du thread auxiliaire qui s’affiche :confused:

Euh je me suis trompé il ne se stoppe pas, mais si je ne m’abuse, en utilisant ce type d’event, cela implique que le thread qui doit réagir à l’event doit controler en controler périodiquement l’état (ici, if ( m_EventStop.WaitOne(0, true) ) dans LongProcess), non ?

non en fait m_EventStop.WaitOne(0, true) et StopThread() sont juste utilisées pour un arrêt forcé de thread worker, c’est tout…
pour avoir plus d’infos : http://www.c-sharpcorner.com/Multithreadin…ssageLoopJS.asp :wink:

>c’est toujours le nom du thread auxiliaire qui s’affiche
hmm
Invoke(m_form.m_DelegateAddString, new Object[] {s}); de thread auxiliaire lance un event qui va appeler AddString de thread principal et qui va passer “s” comme paramètre…
comment tu récuperes le nom de thread ?!

Bon un petit up tardif car je n’ai pas trop eu le temps de m’en occuper ces derniers jours.
J’ai finalement réussit à faire marcher cette technique sur un programme de test : une application fenetrée (avec donc une classe Form1 qui hérite de System.Windows.Forms.Form), et une déclaration au début : Public Delegate Function delegateFonction().
Ensuite dans la classe, une déclaration : Public Shared m_delegateFonction As delegateFonction.
Au chargement du programme (Form1_load), j’initialise la fonction : m_delegateFonction = New delegateFonction(AddressOf fonction_to_call)
Et enfin je lance un thread et j’appelle la fonction depuis le thread avec Invoke : Invoke(m_delegateFonction).

Impeccable, ça marche.

J’ai ensuite essayé de refaire cela sur mon programme et non plus sur un simple exemple, et là les ennuis commencent.
D’abord mon programme est composé d’une classe principale Sample sans interface (c’est une dll), or Invoke est une fonction de System.Windows.Forms.Form. Qu’à cela ne tienne, j’ai fais hériter ma classe Sample de System.Windows.Forms.Form.
Ensuite je case ma traditionelle déclaration : Public Delegate Function delegateFonction().
Puis dans la classe : Public Shared m_delegateFonction As delegateFonction
Au chargement de la dll, je fais : m_delegateFonction = New delegateFonction(AddressOf show_notification)
Puis quand je veux afficher ma notification, je fais depuis le thread auxiliaire : Invoke(m_delegateFonction).

Et là, rien ne se passe :confused:

J’ai essayé de tracer l’execution à l’aide de messages :

MsgBox("Avant Invoke", MsgBoxStyle.Information)
Invoke(m_delegateFonction)
MsgBox("Après Invoke", MsgBoxStyle.Information)

Ainsi qu’un message au début de la fonction show_notification(). Après execution, seul “Avant Invoke” s’affiche, donc il semblerait qu’Invoke fasse planter la dll :frowning:
Je ne comprends pas trop où est la difference avec mon programme de test, si ce n’est que je n’ai pas commencé sur le modèle d’une application fenetrée (avec la classe Form1). Peut-être qu’il faut que je fasse quelques initialisations en plus de faire hériter ma classe de System.Windows.Forms.Form ?

Bon j’ai repéré le problème : en plus de faire hériter ma classe Sample, il faut aussi que je créé une fenêtre. Je vais donc m’arranger pour mettre ladite fenêtre masquée et en arrière plan de manière à utiliser le moins de ressources possible. Merci pour votre aide :slight_smile: