[.NET] Probleme de multithreading

bon, voila, je fais un petit test.
j’essaie de gerer un treeview avec 2 thread different.
un qui met les nodes de depart puis ne fait plus rien et un qui est appelle lorsqu’un node est selectionne et tente de remplir ce node avec 1 autre.
c’est idiot, ca ne sert strictement a rien mais c’est pour tester.

Bien sur comme je suis nul, je n’arrive pas a faire ajouter a mon second thread des nodes au treeview du premier thread :stuck_out_tongue: . J’ai essaye d’utiliser un delegate, je crois qu’il faut quelque part mais je l’utilise certainement mal.

voila donc :

la classe form1 (sans le code genere par vs parce que bon …)

[code]Public Class Form1
   Inherits System.Windows.Forms.Form

#Region " Code généré par le Concepteur Windows Form "
'ici il y avait du code pour initialiser form1 et treeview1 mais c’est sans importance
#End Region

   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
       Dim i As Integer
       For i = 0 To 10
           Dim node As New TreeNode(i.ToString)
           TreeView1.Nodes.Add(node)
       Next
   End Sub

   Public Delegate Function addtotreeview(ByVal text As String) As TreeNode

   Private Sub TreeView1_BeforeSelect(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewCancelEventArgs) Handles TreeView1.BeforeSelect
       Dim d As New addtotreeview(AddressOf e.Node.Nodes.Add)
       Dim a As New sthread(d)
       Dim t As New System.Threading.Thread(AddressOf a.doit)
       t.Start()
   End Sub

End Class[/code]

et ensuite la petite classe de mon thread

[code]Public Class sthread

   Private deleg As Form1.addtotreeview

   Public Sub New(ByVal deleg As Form1.addtotreeview)
       Me.deleg = deleg
   End Sub

   Public Sub doit()
       deleg.Invoke(« useless node »)
   End Sub

End Class[/code]

et pour finir, la superbe erreur:

Une exception non gérée du type ‹ System.InvalidOperationException › s’est produite dans system.windows.forms.dll

Informations supplémentaires : L’action effectuée sur ce contrôle est appelée à partir d’un thread incorrect. Vous devez marshaler le thread correct en utilisant Control.Invoke ou Control.BeginInvoke pour effectuer cette action.

HELP, toute personne illuminee (GloP ou autre) est la bienvenue :P"

Windows marche avec une message pump, c’est a dire un boucle qui tourne et qui processe/distribue/propage/reagit a des messages genre PAINT, MOUSE_MOVE, MOUSE_CLICK, HIT_TEST, etc. Rajouter des elements dans un tree view c’est un message special qui « parle » a ta treeview genre TREEVIEW_RAJOUTE_ELEMENT. Pour des raisons assez evidentes tu te rend vite compte que la boucle qui « pompe » les messages elle doit tourner dans un seul thread, c’est juste un while(GetMessage(& m)) {…} en gros :P. C’est ce qu’on appelle le UI thread, c’est le thread qui gere l’interface utilisateur.

Dans ce cadre, tu peux pas avoir un message qui est lance dans un autre thread que le thread qui contient ta message pump, ca a juste pas de sens. Ca voudrait dire que tu balance un message mais il y a personne pour le rattraper dans le while() qui va bien. Qui va le recuperer, qui va l’envoyer et a qui? Donc il faut que les changement de ta UI qui impliquent un envoi de message soient fait a partir du meme thread que le thread qui contient ta message pump.

Donc… dans ton cas, tu dois depuis le deuxiemme thread, dire au premier thread « est ce que tu peux m’envoyer un message dans la queue de la message pump qui rajoute des elements dans ma treeview stp? ». Et magique… y a toute une interface pour faire ca, et c’est Control.Invoke (en synchrone, tu attend que le thread copain te reponde) ou Control.BeginInvoke (asynchrone, tu dis « balance ca » et tu te casses).

Je suis sur qu’en trouvant sur le net tu peux trouver des dizaines d’exemples de Control.Invoke tout cons pour te montrer comment faire. La c’est en VB et meme si j’ai rien contre ce langage, j’ai carrement du mal a ecrire a la volee sans compilateur avec :stuck_out_tongue:

Ok ok, merci de la clarification.
Je vais aller chercher apres ca. A vrai dire j’avais deja cherche mais pas vraiment trouve, j’en etais donc venu au delegue pour sa methode invoke. Ce n’est pas la bonne voie donc. A force de chercher des trucs par ci par la je finirais bien par me faire une petite liste de sites de reference dotnet ou chercher (hors msdn :stuck_out_tongue: ).

Sinon je comprends pour le vb … j’ai personelement l’habitude du Cpp :stuck_out_tongue: , je suis fan des points virgules, des accolades et des parentheses mais la j’ai pas trop le choix :stuck_out_tongue:

EDIT: wonderful, j’ai un truc qui marche :stuck_out_tongue:
la fraicheur matinale, l’esprit repose, tout ca surement. merci encore B)

[code]Public Class Form1
   Inherits System.Windows.Forms.Form

#Region " Code généré par le Concepteur Windows Form "
’ blablablabla
#End Region

   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
       Dim i As Integer
       For i = 0 To 10
           Dim node As New TreeNode(i.ToString)
           TreeView1.Nodes.Add(node)
       Next
   End Sub

   Public Delegate Function addtotreeview(ByVal text As String) As TreeNode
   Public Shared deleg As addtotreeview

   Private Sub TreeView1_BeforeSelect(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewCancelEventArgs) Handles TreeView1.BeforeSelect
       deleg = AddressOf e.Node.Nodes.Add
       Dim t As New System.Threading.Thread(AddressOf doit)
       t.Start()
   End Sub

   Private Sub doit()
       Dim args(0) As String
       args(0) = « useless node »
       TreeView1.Invoke(deleg, args)
   End Sub

End Class[/code]

Oui un truc comme ca, ca me parait pas trop mal :stuck_out_tongue:

GloP did it again !