Invoke et module

Signaler
Messages postés
10
Date d'inscription
mardi 11 février 2003
Statut
Membre
Dernière intervention
19 mars 2008
-
Anakkin
Messages postés
10
Date d'inscription
mardi 11 février 2003
Statut
Membre
Dernière intervention
19 mars 2008
-
Bonjour,
J'ai un probleme avec un module qui contient des fonctions pour la gestion du thread.
Mon formulaire principal contient un textbox et un bouton.

Le bouton contient cette fonction:
 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        lance_verif()
 End Sub

Lance_Verif() est contenue dans le module Thread.vb:
    Public Sub lance_verif() 
        Thread_connexion = New Threading.Thread(AddressOf Serveur_connexion)
        Thread_connexion.Start()
    End Sub

Jusque la ca va. Le thread lance donc en fond la fonction Serveur_connexion, qui se trouve aussi dans le module thread.vb:


    Public Sub Serveur_connexion()

        Main.Invoke(New AfficheNotifHandler(AddressOf Trace_notif), "Connexion au Serveur en cours ...")

    End Sub

La fonction trace_notif permet d'afficher dans le textbox mon commentaire. Elle fonctionne parfaitement.

Mon probleme demeure sur le Invoke: "Impossible d'appeler Invoke ou BeginInvoke sur un contrôle tant que le handle de fenêtre n'a pas été créé."
Ca marchparfaitement quand je deplace ce code dans le main.vb, mais dans le module thread.vb non.

Il y a t il une méthode pour outrepasser ca?

Merci de votre attention
Iainh

5 réponses

Messages postés
4
Date d'inscription
mercredi 9 juin 2004
Statut
Membre
Dernière intervention
19 mars 2008

Bonjour,

Je désire faire la même chose que toi et j'ai la même erreur.

As-tu trouver la solution à ton problème?

Merci de me donner des nouvelles
Messages postés
10
Date d'inscription
mardi 11 février 2003
Statut
Membre
Dernière intervention
19 mars 2008

Bonjour,

Malhereusement non, Je n'ai pas trouvé de moyen pour sortir les fonctions deleguée du formulaire ou elles vont etre appeler.
J'avoue ne pas avoir investigué plus. J'ai essayé de faire diverses manieres mais la seule qui fonctionne, c'est quand tout est contenu dans le meme formulaire (excepté les declaration des threads qui sont dans le module).

Si jamais tu trouves quelque chose de mieux, tiens moi au courant !

Merci
Messages postés
4
Date d'inscription
mercredi 9 juin 2004
Statut
Membre
Dernière intervention
19 mars 2008

Ok Merci bien Anakkin,


Oui je te tiens au courant si jamais je trouve la solution
Messages postés
4
Date d'inscription
mercredi 9 juin 2004
Statut
Membre
Dernière intervention
19 mars 2008

Bonjour Anakkin,


Voici la solution que j’ai trouvé afin de pouvoir passer dans un module une partie du code initialisé par une form en employant le multithreading. Grosso modo, ce n’est pas la form 1 qui est l’objet de démarrage de l’application. On passe plutôt, par exemple, par une sub main définie dans un module global qui va créer un objet de type form qui va pouvoir être référencé tout au long du code.

C'est pas mal compliqué et le développeur qui travaille avec moi m'a pas mal aidé à décortiquer tout ça. En espérant que tu vas pouvoir comprendre quelque chose et que ça va être aussi utile pour d'autres personnes. C'est peut-être pas le code le plus élégant mais l'important, c'est que ça fonctionne, pour l'instant.

Mais avec ça, ça devrait rendre le code plus clair en permettant de séparer le code dans différent module et ainsi éviter de devoir tout mettre le code dans le même module

Dans ma form, j'ai seulement un label (LblEtatAvancement), une progress bar (ProgressBar1) et un bouton (cmdPartirThread)




Voici ce que ça donne :





1)      il faudra donc définir l’objet de démarrage de la solution (right clic sur le projet/propriété; mettre l’objet de démarrage à Sub Main (préalablement définie)




2)     

Module Global (Mod_Global.vb)<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" /??>





Option

Explicit
On






Module
Mod_Global






   
'variable qui sert à setter le maximum du progress bar







   

Public
MaxValue AsDouble






   
Public
Sub
<?xml:namespace prefix st1 ns "urn:schemas-microsoft-com:office:smarttags" /??>
<st1:place w:st="on">Main</st1:place>()






        Application.EnableVisualStyles()






        Application.SetCompatibleTextRenderingDefault(False)






        Application.Run(Form1.Current())






   
    

End Sub








End Module





3)      Form qui contient l’interface et l’appel du thread (Form1.vb)



Option

Explicit
On






Imports
System.Threading





Public

Class Form1






   
Private
Shared MyForm As Form1






   
Public
Shared
ReadOnly
Property Current() As Form1






       
Get







           
If MyForm IsNothingThen






                MyForm = New Form1






           
End
If







           
Return MyForm






       
End
Get







   
End
Property







 







   
Dim thExecuteTaskAsync As Thread = Nothing






 







   
Private
Sub ThreadComplete()






       
Dim LeTexte AsString






        LeTexte = "Opération terminée"






        Invoke(ShowStatus, NewObject() {LeTexte})






        Invoke(OperationTerminee, Nothing)






       
If
Not thExecuteTaskAsync IsNothingThen






            thExecuteTaskAsync.Abort()






            thExecuteTaskAsync.Join()






            thExecuteTaskAsync = Nothing






       
End
If







   
End
Sub







   
'=============================================================







   
Private
Sub Form1_FormClosing(ByVal sender AsObject, ByVal e As System.Windows.Forms.FormClosingEventArgs) HandlesMe.FormClosing






       
'this is necessary if the form is trying to close, even before the completion of task







       
If
Not thExecuteTaskAsync IsNothingThen thExecuteTaskAsync.Abort()






   
End
Sub







 







   
'================================================================







   
''DELEGATE declaration







   
Public
Delegate
Sub delShowStatus(ByVal Texte AsString)






   
Public
Delegate
Sub delShowPrg(ByVal i AsDouble)






   
Public
Delegate
Sub delMAJProgressBar()






   
Public
Delegate
Sub delOperationTerminee()






   
Public ShowStatus AsNew delShowStatus(AddressOf ShowMsg)






   
Public ShowProgress AsNew delShowPrg(AddressOf ShowPrg)






   
Public OperationTerminee AsNew delOperationTerminee(AddressOf subOperationTerminee)






   
Public MAJProgressBar AsNew delMAJProgressBar(AddressOf subMAJProgressBar)






 







   
Private
Sub ShowMsg(ByVal leTexte AsString)






       
Me.LblEtatAvancement.Text = leTexte






   
End
Sub







 







   
Private
Sub ShowPrg(ByVal i AsDouble)






       
Me.ProgressBar1.Value = i






   
End
Sub







 







   
Private
Sub subOperationTerminee()






       
Me.cmdPartirThread.Text = "Recommencer ?"






   
End
Sub







 







   
Private
Sub subMAJProgressBar()






       
Me.ProgressBar1.Maximum = MaxValue






   
End
Sub







 







   

Private

Sub
New()






 







       
' Cet appel est requis par le Concepteur Windows Form.







        InitializeComponent()






 







       
' Ajoutez une initialisation quelconque après l'appel InitializeComponent().







 







   

End

Sub







 







   
Private
Sub cmdPartirThread_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdPartirThread.Click






       
If cmdPartirThread.Text = "Annuler"Then






           
If
Not thExecuteTaskAsync IsNothingThen






   
            thExecuteTaskAsync.Abort()






                thExecuteTaskAsync.Join()






                thExecuteTaskAsync = Nothing






           
End
If







           
'on appelle le ShowMsg via le ShowStatus







            Invoke(ShowStatus, NewObject() {CType(0, String)})






           

Me
.ProgressBar1.Minimum = 0






           
Me.LblEtatAvancement.Text = "Opération annulée"






           

cmdPartirThread.Text = "Recommencer ?"






       
Else







            cmdPartirThread.Text = "Annuler"






           

LblEtatAvancement.Text = "Traitement en cours..."






 







           

MaxValue = 10000






           
Me.ProgressBar1.Minimum = 0






           
Me.ProgressBar1.Maximum = MaxValue






 







           
If
Not thExecuteTaskAsync IsNothingThen






                thExecuteTaskAsync.Abort()






                thExecuteTaskAsync.Join()






                thExecuteTaskAsync = Nothing






           
End
If







           
'start a new thread to execute the task asynchronously







            thExecuteTaskAsync = New Thread(AddressOf GestionCheckBox)






            thExecuteTaskAsync.Start()






       
End
If







   
End
Sub







 







   
Private
Sub GestionCheckBox()






        Mod_Tache.LongueTache()






        ThreadComplete()






   
End
Sub






End

Class






4)      Finalement, le module qui contient le code qui fait la procedure longue (Mod_Tache.vb)



Option

Explicit
On






Imports
System.Threading





Module
Mod_Tache






   
Public
Sub LongueTache()






        MaxValue = 100000






        Form1.Current.Invoke(Form1.Current.MAJProgressBar, Nothing)






       
Dim cpt AsInteger






       
Dim cptTotal AsDouble






       
Dim intx AsDouble






        cpt = 0






        cptTotal = 0






       
For intx = 0 To MaxValue






           
'à chaque 1%, on montre la progression, ce qui est pas mal fluide
            'pourquoi un intervalle de 1%, parce que l'invoke relentit pas mal la procédure, 
            'donc, le moins possible le invoke







           

If

CInt(cpt / MaxValue * 100) >= 1 Then     '1%






                cpt = 0






               
'access delegate to show status on GUI







  
             

Dim
Letexte AsString






                Letexte = "Opération en cours:  " & CInt(cptTotal / MaxValue * 100) & "% effectué"






               

Form1.Current.Invoke(Form1.Current.ShowStatus, NewObject() {Letexte})






                Form1.Current.Invoke(Form1.Current.ShowProgress, NewObject() {cptTotal})






           

End

If







 







           
'Pause à chaque 10000, pour ne pas que ça se fasse trop rapidement







           

If
intx Mod 10000 = 0 Then






                Thread.Sleep(1000)






           
End
If







 







       
    cpt = cpt + 1






            cptTotal = cptTotal + 1






       
Next intx






   
End
Sub






End

Module







 





 
Messages postés
10
Date d'inscription
mardi 11 février 2003
Statut
Membre
Dernière intervention
19 mars 2008

Je te remercie pour tout ca
Je vais regarder tout ca de plus près

Bonne soirée