IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Forms Discussion :

Executer le traitement dans un thread ou BackgroundWorker


Sujet :

Windows Forms

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    614
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 614
    Points : 299
    Points
    299
    Par défaut Executer le traitement dans un thread ou BackgroundWorker
    Hello,
    j'ai fait des recherches sur google, forum, sur l'utilisation des threads et je n'arrive toujours pas a comprendre comment le mettre en oeuvre dans mon cas.
    j'explique, j'ai une form qui contient plusieurs textboxes.
    j'ai un bouton qui me permet de creer un .doc et ensuite converti ce .doc en PDF.
    Le probleme c'est que cette petite fonctionnalité fige quelques instant l'application complete.
    J'ai donc pensé a faire ce traitement dans un thread separé.
    (je suis tombé sur un post qui expliquais cela http://www.developpez.net/forums/d63...ultithreading/ mais je n'ai toujours pas compris.
    j'ai l'erreur suivante quand je tente de passer le traitement au thread:
    Opération inter-threads non valide: le contrôle 'frmLauncherBo' a fait l'objet d'un accès d'un thread autre que celui sur lequel il a été créé.
    Vous allez me dire ,
    il suffit de sortir tout le code qui touche de près ou de loin aux composants winform dans une fonction externe de d'y ajouter la vérification à l'aide de InvokeRequiered
    mais cela ne me parle pas vraiment.....
    tomlev a parlé de BackgroundWorker qu'est ce que cela est?
    Comment cmet on en oeuvre ce mechanisme.
    Merci de votre aide et de vos lumiere.

    un extrait de mon code ;
    j'ai declaré mon thread
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    private Thread _threadPDF;
    puis defini la methode StartThread:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     private void StartThread()
            {
                // ThrFunc est la fonction exécutée par le thread.
                _threadPDF = new Thread(new ThreadStart(ExportToPDF));
                // Il est parfois pratique de nommer les threads surtout si on en créé plusieurs.
                _threadPDF.Name = "Thread1";
                // Démarrage du thread.
                _threadPDF.Start();
            }
    et la ou j'appel d'habitude ExportToPDF j'appel StartThread

  2. #2
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Regarde le tuto du composant BackgroundWorker, cela te suffira peut être.
    Pas de questions techniques par MP

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    614
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 614
    Points : 299
    Points
    299
    Par défaut
    merci j'avais commencé a le lire, mais je ne comprends pas comment transposer son exemple dans mon cas.
    Dans le tuto il fait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bgwDesign.RunWorkerAsync((int)nudNbLoop.Value);
    il passe en parametre le nbLoop.
    Moi dans mon cas je souhaite passer ....(je ne sais pas) puisque c'est une fonction ExportToPDF
    (je ne la met pas entiere elle est trop longue.
    Mais voici un extrait.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    PrintDocument prtdoc = new PrintDocument();
                DefPrinter = prtdoc.PrinterSettings.PrinterName;
    //creation d'un .doc a partir des champs de ma form
                CreateDoc(iTypeDoc, false);
    
                string fname, DefaultPrinter;
                string fi2 = string.Empty;
                PDFCreator.clsPDFCreatorOptions opt;
                pErr = new PDFCreator.clsPDFCreatorError();
    
                _PDFCreator = new PDFCreator.clsPDFCreator();
    ....
    As tu une idée de qu'est ce que je devrais mettre en parametre ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    BGW_PDF.RunWorkerAsync(????);

  4. #4
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Tu passes en paramètre ce dont tu as besoin. Le nom du fichier .doc à imprimer en PDF par exemple.

    Mais tu n'es pas obligé de passer quelque chose en paramètre, les informations nécessaires peuvent être stockées dans des champs privés de la classe au besoin.

    Bref, à toi de voir les entrées nécessaires à ton traitement afin de déterminer les paramètres nécessaires.
    Pas de questions techniques par MP

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    614
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 614
    Points : 299
    Points
    299
    Par défaut
    Desolé je ne suis pas sur de comprendre...
    Je souhaite passer au BGW tout le traitement, c'est a dire la creation du .doc ainsi que la convertion en PDf.
    tout cela se fait dans la fonction ExportToPDF.
    donc, je ne comprends pas trop comment lui passer cela

  6. #6
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Tu n'as pas à lui passer le traitement, tu n'as pas bien lu le tuto.

    Le BackgroundWorker fourni un événement DoWork et c'est dans la méthode associée à cet événement que tu dois faire ton traitement : appeler ExportToPDF avec le nom complet du fichier doc à convertir par exemple. Sachant que ce code sera exécuté dans un thread à part.

    Reprend le tuto, sans lire en diagonale ^^
    Tout ce qu'il te faut est là
    Pas de questions techniques par MP

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    614
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 614
    Points : 299
    Points
    299
    Par défaut
    Lu oui, compris pas tout a fait....
    j'ai bien compris que c'est dans la method qu'il faut lui indiquer le traitement a faire.
    Ce que j'ai fait mais il veut pas convertir un vois en object:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     private void BGW_PDF_DoWork(object sender, DoWorkEventArgs e)
           {
               BackgroundWorker worker = sender as BackgroundWorker;
               e.Result = ExportToPDF();//cannot......
           }

  8. #8
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Il ne faut pas toujours appliquer les tutos à la lettre. Le tuto montre généralement le principe, après il faut utiliser ses neurones, le Web (google, MSDN, ...) et pas juste copier / coller le code "bêtement"

    La propriété Result permet "de définir une valeur qui représente le résultat d'une opération asynchrone" (cf. doc MSDN). Ca permet donc de stocker le résultat du traitement qui est fait dans le thread à part, pour pouvoir y accéder ensuite au niveau de l'événement RunWorkerCompleted.

    Mais tout ceci à condition bien évidemment que le traitement en question ait un résultat à renvoyer. Ce n'est pas ton cas puisque la méthode ExportToPDF renvoie void.

    Ton code devrait donc ressembler à ceci plutôt
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    private void BGW_PDF_DoWork(object sender, DoWorkEventArgs e)
    {
        ExportToPDF();    
    }
    Pas de questions techniques par MP

  9. #9
    Membre actif
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    614
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 614
    Points : 299
    Points
    299
    Par défaut
    oui je m'en suis rendu compte apres avoir compris que la fonction traitement etait pas obligatoire au BGW...
    Par contre je rencontre l'erreur suivante la meme que j'ai eu lorsque j'ai tenté de le faire avec un thread.
    Cross-thread operation not valid: Control 'cbFormat' accessed from a thread other than the thread it was created on.
    je ne comprends pas ce que dit le tuto:
    Que ce soit dans l'envent handler du DoWork ou dans la méthode Treatment, il est totalement interdit de manipuler les contrôles de l'interface utilisateur. En effet, ces deux méthodes ne s'exécutent pas dans le thread de l'interface et par conséquent les valeurs de ces contrôles pourraient changer ou l'avoir été ! Par contre les event handler des évènements ProgressChanged et RunWorkerCompleted sont là pour ça car ils s'exécutent dans le même thread que l'interface. De plus n'oubliez pas de bien passer tous vos paramètres à la méthode RunWorkerAsync car c'est le seul moyen de récupérer des paramètres dans le traitement.

  10. #10
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    C'est pourtant clair je trouve, mais bon c'est facile à dire pour moi.

    Que ce soit dans l'event handler du DoWork ou dans la méthode Treatment, il est totalement interdit de manipuler les contrôles de l'interface utilisateur.
    Tu n'as pas le droit de manipuler un contrôle graphique dans un thread autre que le thread principal. La méthode associée à l'événement DoWork (event handler du DoWork) et tous les appels qui en découlent (i.e. les méthodes appelées depuis l'event handler du DoWork) ne doivent donc pas toucher aux contrôles.

    Ta Combo sert probablement à faire une sélection qui va impacter le traitement. C'est donc un paramètre de ton traitement et il faut que tu le gères en tant que tel.
    De plus n'oubliez pas de bien passer tous vos paramètres à la méthode RunWorkerAsync car c'est le seul moyen de récupérer des paramètres dans le traitement.
    Pas de questions techniques par MP

  11. #11
    Membre actif
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    614
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 614
    Points : 299
    Points
    299
    Par défaut
    En fait dans ma fonction ExportToPDF je fais appel a CreateDoc() qui genere un .Doc
    voici une partie du code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
     public void CreateDoc(int NumRelance, bool IsVisible) 
     
            {.....
    field = "CP";
                    nvDoc.FormFields.get_Item(ref field).Result = tBoxCPClient.Text;
     
                    field = "Ville";
                    nvDoc.FormFields.get_Item(ref field).Result = tBoxVille.Text;
     
     
                    field = "Format";
                    nvDoc.FormFields.get_Item(ref field).Result = cbFormat.SelectedItem.ToString();//ici ca plante
    .....
    j'ai compris que on a pas le droit d'utiliser des controls qui sont dans le DoWork parcequ'ils sont pas dans le meme thread.
    Premiere question, pourquoi ca plante qu'a l'utilisation de la combo et pas avant?
    De plus quand tu dis:
    C'est donc un paramètre de ton traitement et il faut que tu le gères en tant que tel.

    De plus n'oubliez pas de bien passer tous vos paramètres à la méthode RunWorkerAsync car c'est le seul moyen de récupérer des paramètres dans le traitement.
    je ne comprends pas vraiment dois je passer en parametre TOUS les controles de ma form?

  12. #12
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Premiere question, pourquoi ca plante qu'a l'utilisation de la combo et pas avant?
    Parce que la propriété SelectedItem doit agir sur le contrôle contrairement à la propriété Text. C'est pour ça qu'avec les TextBox s'est passé comme une lettre à la poste. Mais l'idéal reste de ne pas manipuler de contrôles et de tout passer en paramètre via la surcharge de la méthode RunWorkerAsync. Et si tu as plusieurs paramètres tu déclares une structure pour stocker l'information et tu passes tout ça à la méthode.

    je ne comprends pas vraiment de plus, je ne vois pas la méthode RunWorkerAsync en tant qu'event de BGW
    RunWorkerAsync n'est pas un événement, c'est une méthode. C'est cette méthode qui sert à démarrer le traitement en déclenchant l'événement DoWork.
    Pas de questions techniques par MP

  13. #13
    Membre actif
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    614
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 614
    Points : 299
    Points
    299
    Par défaut
    ok, par contre comme ca s'execute de maniere asynchrne et qu'il ya un appel d'un deuxieme fonction dans certains cas ca plante...
    Merci de ton aide en tout cas.

  14. #14
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Août 2005
    Messages
    1
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 1
    Points : 1
    Points
    1
    Par défaut
    Salut,

    En fait ça plante des que tu touches à la combo car les controles graphiques n'ont pas le droit d'etre modifiés depuis un autre thread que le thread pricipal.
    Pour que cela fonctionne, il faut que la méthode qui modifie l'affichage soit appelée via un Invoke.

    macombo.Invoke( ... )

    Hope it helps

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Architecture de mon algorithme: quand séparer un traitement dans un thread ?
    Par billybobbonnet dans le forum Windows Presentation Foundation
    Réponses: 42
    Dernier message: 17/10/2014, 14h59
  2. Réponses: 3
    Dernier message: 14/07/2010, 14h27
  3. Forcer l'execution d'une fonction dans un thread
    Par greg2 dans le forum Threads & Processus
    Réponses: 3
    Dernier message: 24/11/2009, 14h34
  4. Problème d'execution de code dans un thread
    Par [Silk] dans le forum Langage
    Réponses: 2
    Dernier message: 06/02/2006, 13h49
  5. [Process]Execution de process dans un thread
    Par devjava dans le forum Concurrence et multi-thread
    Réponses: 5
    Dernier message: 18/06/2004, 10h34

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo