Gérer les inter-threads avec un BackgroundWorker

cs_aus3004 Messages postés 319 Date d'inscription jeudi 1 avril 2010 Statut Membre Dernière intervention 16 mars 2011 - 5 nov. 2010 à 22:09
cs_aus3004 Messages postés 319 Date d'inscription jeudi 1 avril 2010 Statut Membre Dernière intervention 16 mars 2011 - 7 nov. 2010 à 10:48
Bonjour,

J'ai une fonction qui prend 30 secondes à s’exécuter et qui bouffe tout le programme pour ensuite freezer.

J'ai donc pensé à utiliser un BackgroundWorker vu que la fonction est une mise à jour, et c'est pas gênant si elle prend du tant à s’exécuter tant que le prog fonctionne à côté. Je test, puis je tombe sur l'erreur :
Opération inter-threads non valide : le contrôle 'Main' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé.

au milieu de la fonction.
Je regarde ensuite comme solutionner cet inter-thread et je remarque que pour que cela fonctionne il faut modifier toute la fonction, chaque opération doit être adaptée à cet effet.

Le problème est que ma fonction est très longue et variée et là je suis un peu perdu
C'est la première fois que j'utilise ce composant.
Je voudrais savoir si on peut facilement adapter une fonction entière pour qu'elle fonctionne en inter-threads.

Zavez pas une idée ?
Merci et bon dev

Ma LV2 c'est le Visual Basic, et toi ?

11 réponses

NHenry Messages postés 15113 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 22 avril 2024 159
6 nov. 2010 à 00:10
Bonjour,

Oui, par exemple :

Private Delegate Function DlgMaFonction(ByVal pValue as integer) as string

Private Function MaFonction(ByVal pValue as integer) as string
    If Me.InvokeRequired then
        Return me.Invoke(new DlgMaFunction(AddressOf MaFonction),new object(){pValue})
    End If

    Return pValue.ToString()
End Function


0
cs_aus3004 Messages postés 319 Date d'inscription jeudi 1 avril 2010 Statut Membre Dernière intervention 16 mars 2011 1
6 nov. 2010 à 10:28
C'est bien sur cet même exemple que j'étais bloqué.
En faite, je comprend pas le pValue, c'est quoi ?
Si je ne prend pas compte de cet déclaration mon code est :

Private Delegate Function DlgMaFonction()
    Private Function POP_Gmail()
        If Me.InvokeRequired Then
            Return Me.Invoke(New DlgMaFonction(AddressOf POP_Gmail), New Object())
        End If
     ' Le code de ma fonction
    End Function

Private Sub BGW2_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BGW2.DoWork
        POP_Gmail()
    End Sub


Mais comme ca j'ai l'erreur : Nombre de paramètres incorrects.

Ma LV2 c'est le Visual Basic, et toi ?
0
NHenry Messages postés 15113 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 22 avril 2024 159
6 nov. 2010 à 13:58
Bonjour,

Comme tu n'as pas de paramètre, normalement, tu devrait utiliser l'autre surcharge :
Return Me.Invoke(New DlgMaFonction(AddressOf POP_Gmail))

Je l'ai surtout utilisé pour les subs, mais ça devrait fonctionner.

(note, ça te retourne un Object, il faudra caster, je pense.

0
cs_aus3004 Messages postés 319 Date d'inscription jeudi 1 avril 2010 Statut Membre Dernière intervention 16 mars 2011 1
6 nov. 2010 à 14:27
Merci j'ai remplacé ta ligne de code, et il n'y a pas d'erreur.
Pourtant le programme ne répond pas comme avant, comme si le backgroundworker n'existait pas.
J'ai oublié quelque chose ?

Ma LV2 c'est le Visual Basic, et toi ?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Utilisateur anonyme
6 nov. 2010 à 14:50
Salut à tous les 2,

Je viens d'essayer une méthode qui fonctionne mais je ne sais pas si ça se fait comme ça et s'il n'y a pas un moyen plus simple :

Public Class Form1
    Private Delegate Sub MaSubDelegate(ByVal ResultatFonction As Integer)

    'nouveau label
    Dim Label1 As New Label With {.Text "Attente résultat...", .Parent Me, .ForeColor = Color.BlueViolet}

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        'lancement du thread
        BGW2.RunWorkerAsync()
    End Sub

    Private Sub BGW2_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BGW2.DoWork
        If Me.InvokeRequired Then Me.Invoke(New MaSubDelegate(AddressOf MaSub), Pop_Gmail)
    End Sub

    Private Function Pop_Gmail() As Integer
        'boucle bidon pour simuler un long calcul
        For x As Integer = 0 To 900000000
        Next

        'résultat bidon pour le test
        Return 456789
    End Function

    Private Sub MaSub(ByVal ResultatFonction As Integer)
        'résultat contient le résultat de la fonction
        Label1.Text = ResultatFonction.ToString
    End Sub

End Class


Bonne après-midi.
0
NHenry Messages postés 15113 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 22 avril 2024 159
6 nov. 2010 à 16:50
Bonjour,

Banana32,
J'ai essayé cette syntaxe, et avec mon VS2005, il me jette sur le With et suivant car il attend la fin de la ligne, tu bosse avec quelle version ?
Dim Label1 As New Label With {.Text = "Attente résultat...",

Ensuite,
Ton exemple, tu calcule Pop_GMail dans le thread et tu passe la valeur dans le paramètre de MaSub qui elle est synchrone avec la form.

ça peut être une bonne idée :)
Reste à savoir si ça peut fonctionner dans le cas de la demande.


0
Utilisateur anonyme
6 nov. 2010 à 17:09
Salut NHenry,
J'utilise VB 2008 express edition.
Mon exemple ne marchera pas car en relisant le problème, dans sa fonction il y a un contrôle genre label placé sur un formulaire qui doit être appelé pendant l'exécution de la fonction.
Il aurait été utile qu'on ait le code de la fonction Pop_Gmail en question pour tenter de supprimer tout accès à n'importe quel contrôle dans la fonction et de les mettre à jour une fois celle-ci exécutée.
On verra bien
A bientôt.
0
cs_aus3004 Messages postés 319 Date d'inscription jeudi 1 avril 2010 Statut Membre Dernière intervention 16 mars 2011 1
6 nov. 2010 à 17:32
Salut banana32, merci de t'être joint à la discussion.

Comme je le pensais au début il ne suffit pas de rajouter une ligne de code au début et à la fin de la fonction pour que le problème soit résolu. Il faut modifier des éléments particuliers dans la fonction qui font appel à des composants.

Ok, tu veux inspecter ma fonction ?

Ma LV2 c'est le Visual Basic, et toi ?
0
cs_aus3004 Messages postés 319 Date d'inscription jeudi 1 avril 2010 Statut Membre Dernière intervention 16 mars 2011 1
6 nov. 2010 à 17:34
Parce que le problème est que la fonction utilise d'autres fonctions et à la fin ca fait tout le code de mon projet

Ma LV2 c'est le Visual Basic, et toi ?
0
Utilisateur anonyme
7 nov. 2010 à 00:16
la fonction utilise d'autres fonctions et à la fin ca fait tout le code de mon projet


Peut être que le moment est venu de restructurer complètement ton code en prenant en compte les contraintes liées aux threads.
Personnellement c'est ce que je ferais à ta place (ça m'arrive souvent ). Ou bien tu te retrouvera avec "une usine à gaz" impossible à gérer.
A bientôt.
0
cs_aus3004 Messages postés 319 Date d'inscription jeudi 1 avril 2010 Statut Membre Dernière intervention 16 mars 2011 1
7 nov. 2010 à 10:48
Je t'ai envoyé un MP contenant tout le code.
@NHenri, si cela t'interesse je peux également te faire parvenir mon code.
Merci à tous.

Ma LV2 c'est le Visual Basic, et toi ?
0
Rejoignez-nous