shackleton1986
Messages postés9Date d'inscriptionjeudi 12 janvier 2006StatutMembreDernière intervention21 mars 2007
-
12 mars 2007 à 11:45
NHenry
Messages postés15032Date d'inscriptionvendredi 14 mars 2003StatutModérateurDernière intervention26 janvier 2023
-
19 mars 2008 à 15:32
Je vais essayer mon problème de la manière la plus simple ...
Mon but est de pouvoir modifier un contrôle TextBox de ma fenêtre principale à partir de threads lancés dans des instances d'objets de ma fenêtre principale. Je pense qu'un bout de code vous éclairera un peu plus sur mes objectifs :
Imports System
Imports System.Threading
Imports System.Text
Public Class Form1
Dim threadFils As Class1
Dim threadNb As Integer = 0
Delegate Sub SetTextDelegate(ByVal Text As String)
Public Dim SetTextMarshaler As SetTextDelegate = AddressOf Me.setText
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
TextBox1.Text = "Hello !"
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
threadNb += 1
setText("Création de l'instance " & CStr(threadNb))
threadFils = New Class1(threadNb)
threadFils.launch()
End Sub
Private Sub setText(ByVal Text As String)
TextBox1.Text &= vbCrLf & Text
End Sub
End Class
Public Class Class1
Private id As Integer
Public Sub New(ByVal monId As Integer)
id = monId
End Sub
Public Sub main()
SyncLock Me
'Ces deux lignes ont pour but d'afficher dans la forme principale
'les traces d'éxécution de ce thread
Dim args() As Object = {"Thread " & CStr(id) & " lancé ..."}
Form1.Invoke(Form1.SetTextMarshaler, args)
End SyncLock
End Sub
Public Sub launch()
Dim thread As New Thread(AddressOf main)
thread.Start()
End Sub
End Class
J'ai donc utilisé des délégués et la méthode invoke de la classe Form1 mais sans succès. J'ai vu des exemples qui fonctionnent losque c'est le même objet qui appel la méthode invoke et qui crée le thread. Hors là, mon thread est crée dans une autre classe :s
Je pense qu'il ne me manque pas grand chose mais pour l'instant je suis bloqué.
Merci d'avance :)
shackleton1986
Messages postés9Date d'inscriptionjeudi 12 janvier 2006StatutMembreDernière intervention21 mars 2007 12 mars 2007 à 13:39
Merci pour ta réponse mais je n'arrive toujours pas à faire fonctionner mon programme.
Je suis sous .NET2 (2005) j'ai donc essayé d'utiliser My.Forms.Form1 sans succès :
--> Méthode exécutée par le thread dans Class1 :
Public Sub main()
SyncLock Me
My.Forms.Form1.SetTextMarshaler("Thread " & CStr(id) & " lancé ...")
End SyncLock
End Sub
J'ai aussi essayé de cette manière là :
Public Sub main()
SyncLock Me
Dim args() As Object = {"Thread " & CStr(id) & " lancé ..."}
My.Forms.Form1.Invoke(My.Forms.Form1.SetTextMarshaler, args)
End SyncLock
End Sub
Aurais-tu la syntaxe exact a utiliser ou la méthode pour réaliser ce que je veu ?
shackleton1986
Messages postés9Date d'inscriptionjeudi 12 janvier 2006StatutMembreDernière intervention21 mars 2007 12 mars 2007 à 13:42
En fait avec cette méthode ci :
Public Sub main()
SyncLock Me
Dim args() As Object = {"Thread " & CStr(id) & " lancé ..."}
My.Forms.Form1.Invoke(My.Forms.Form1.SetTextMarshaler, args)
End SyncLock
End Sub
J'obtiens l'exception suivante "InvalidOperationException : Impossible d'appeler Invoke ou BeginInvoke sur un contrôle tant que le handle de fenêtre n'a pas été créé."
Est ce que tu sais d'où cela vient ?
Vous n’avez pas trouvé la réponse que vous recherchez ?
DominicLavoie
Messages postés4Date d'inscriptionmercredi 9 juin 2004StatutMembreDernière intervention19 mars 2008 19 mars 2008 à 14:05
Bonjour NHenry,
J'ai sensiblement le même problème (même erreur du moins) lorsque j'essai
d'appeller <st1:personname productid="la méthode Invoke" w:st="on">la méthode
Invoke</st1:personname> à partir d'un module, mais où le thread a été
initialiser à partir d'une form. Je vois aussi que l'erreur va être évitée si
on charge la fenêtre avant de faire le Invoke.
Mais j'ai quand même un problème. Comme mon application est de type Windows
Form, le formulaire principale est chargée à l'ouverture de l'application.
L'usager choisi différentes opérations qu'il désire effectuées et clique sur un
bouton qui va prendre beaucoup de temps à s'exécuter. C'est là que j'ai besoin
de faire du multithreading afin de montrer à l'écran l'évolution (progress bar
et label) de l'opération qui prend du temps.
Mais comme le formulaire est chargé, <st1:personname productid="la ligne My.Forms" w:st="on">la ligne My.Forms</st1:personname>.Form1.Show montre
à nouveau le formulaire, ce qui ne doit, évidemment pas, survenir.
Comment je fais pour que le formulaire n'apparaisse pas tout en ayant la
possibilité de séparer le code dans le formulaire et dans des modules.
NHenry
Messages postés15032Date d'inscriptionvendredi 14 mars 2003StatutModérateurDernière intervention26 janvier 2023156 19 mars 2008 à 15:32
Bonjour
Soit tu utilises un BackGroundWorker (ne me demande pas d'aide, je ne l'ai jamais utilisé), soit tu mets dans une variable globale la Form qui sert de synchro et ton thread va l'utiliser pour intervenir.
Sinon, une autre approche (celle que je préfère), Tu mets en global une variable structurée qui permet au thread de signaler son avancée, puis avec un Timer, tu récupère ces infos que tu affiches (donc pas besoin de synchro d'affichage).
Pour masquer un Form sans la déchargée, tu peux utiliser la méthode Hide().
Nous captons le cockpit coupable qui a capoté
VB (6, .NET1&2), C++, C#.Net1