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

C# Discussion :

utilisation de BackgroundWorker


Sujet :

C#

  1. #1
    Membre averti
    Inscrit en
    Octobre 2010
    Messages
    38
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 38
    Par défaut utilisation de BackgroundWorker
    Bonjour,
    Je suis débutante en c#,et j'ai besoin d'aide.
    J'ai 3 fonction qui effectue un calcul trop long et j'aimerai les intégrer dans un "BackgroundWorker" afin que mon formulaire ne freeze(bloque) pas,j'ai consulté plein de tuto mais j'ai pas su comment faire.

  2. #2
    Membre émérite
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2007
    Messages
    693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 693
    Par défaut
    Bonjour,

    L'utilisation du BackgroundWorker est assez simple. Les traitements doivent être effectués dans le DoWork et le résultat sera retourné dans le RunWorkCompleted.

    Voici l'initialisation simple d'un backgroundworker :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    BackgroundWorker bw = new BackgroundWorker();
    Son paramétrage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
                bw.WorkerReportsProgress = true;
                bw.WorkerSupportsCancellation = true;
                bw.DoWork += new DoWorkEventHandler(bw_DoWork);
                bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
                bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
    WorkerReportsProgress : permet de dire que ton backgroundworker pourra retenir des informations d'avancement du traitement
    WorkerSupportsCancellation : permet de dire que le traitement de ton backgroundworker pourra être interrompu
    bw.DoWork += new DoWorkEventHandler(bw_DoWork) => l'abonnement au DoWork pour mettre ton traitement dans ta méthode bw_DoWork
    Idem pour progresschanged et RunWorkerCompleted

    Voici à quoi peuvent ressembler ces méthodes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
            private void bw_DoWork(object sender, DoWorkEventArgs e)
            {
                BackgroundWorker worker = sender as BackgroundWorker;
     
                for (int i = 1; (i <= 10); i++)
                {
                    if ((worker.CancellationPending == true))
                    {
                        e.Cancel = true;
                        break;
                    }
                    else
                    {
                        // Perform a time consuming operation and report progress.
                        System.Threading.Thread.Sleep(500);
                        worker.ReportProgress((i * 10));
                    }
                }
            }
            private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                if ((e.Cancelled == true))
                {
                    this.tbProgress.Text = "Canceled!";
                }
     
                else if (!(e.Error == null))
                {
                    this.tbProgress.Text = ("Error: " + e.Error.Message);
                }
     
                else
                {
                    this.tbProgress.Text = "Done!";
                }
            }
            private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                this.tbProgress.Text = (e.ProgressPercentage.ToString() + "%");
            }
    Et pour lancer le traitement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
                if (bw.IsBusy != true)
                {
                    bw.RunWorkerAsync();
                }
    Et pour finir tu remarqueras que toute cette explication est disponible dans MSDN

  3. #3
    Membre averti
    Inscrit en
    Octobre 2010
    Messages
    38
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 38
    Par défaut
    et les fonction que j'ai créer je les mets ou?

  4. #4
    Membre très actif
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2010
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2010
    Messages : 237
    Par défaut
    j'ai mis mes fonctions(3fonction) dans le dowork et le runwork. je sais pas si c'est la qu'il faut les mettre ou pas.
    la première fonction s'exécute une fois arrivée à la deuxième l'erreur suivante apparaît:

    Opération inter-thread invalid: le controle 'chart3' à fait l'objet d'un accès a partir d'un thread autre que celui sur lequel il a été crée
    Sachant que je récupère des données saisie par l'utilisateur sur mon interface pour faire les calculs.

    une solution pour ça???

  5. #5
    Membre émérite
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2007
    Messages
    693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 693
    Par défaut
    Infose => Tu les mets dans le DoWork !
    Kensem => L'erreur est normale, tu tentes d'accéder à un contrôle graphique créé dans le thread UI (thread principal), tu obtiens donc une erreur d'accès inter-thread. La mise à jour des contrôles ne peuvent pas être effectués dans le doWork, il faut le faire par exemple dans le RunWorkCompleted qui lui s'exécute dans le thread appelant du backgroundworker.

  6. #6
    Membre très actif
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2010
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2010
    Messages : 237
    Par défaut
    Bon comme j'ai dis j'ai 3 fonction a appelé je les ai toutes mise dans 'runworker' comme vous m'avez expliqué,or ça marche pas.

  7. #7
    Membre émérite
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2007
    Messages
    693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 693
    Par défaut
    Dire que ça ne marche pas ne veut rien dire, ce n'est pas constructif et n'aide pas à avancer.

    Il faut transmettre le message d'erreur obtenu et si c'est toujours un problème d'opérations inter-thread, j'ai déjà répondu dans mon poste précédent.

    Et je me corrige aussi car quand je dis "La mise à jour des contrôles ne peuvent pas être effectués dans le doWork" c'est pas totalement juste. j'aurai dû dire la mise à jour des contrôles ne peuvent être effectuée dans le thread du doWork, il est possible de faire un Invoke pour exécuter l'opération sur le thread du contrôle.

  8. #8
    Membre très actif
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2010
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2010
    Messages : 237
    Par défaut
    j'ai pas d'erreurs mais mon interface freeze toujours même si j'ai mis toute mes fonction dans le runwork.

    J'ai pas trop saisi ce que vous voulez dire par Invoke??

  9. #9
    Membre émérite
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2007
    Messages
    693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 693
    Par défaut
    Pour le Invoke, j'ai voulu dire ça

    Pour le reste va falloir montrer du code et donner plus de détail sur ce qui est fait et comment !

  10. #10
    Membre très actif
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2010
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2010
    Messages : 237
    Par défaut
    le même code que t'as posté ;j'ai changé juste ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
            private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                if ((e.Cancelled == true))
                {
                    this.Text = "Canceled!";
                }
     
                else if (!(e.Error == null))
                {
                    this.Text = ("Error: " + e.Error.Message);
                }
     
                else
                {
     
                    if (checkBox1.Checked)
                    {
                        calcul_natural(sender, e);
                    }
                    if (checkBox2.Checked)
                    {
                        sequence1(sender, e);
                    }
     
     
     
     
     
            }

  11. #11
    Membre émérite
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2007
    Messages
    693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 693
    Par défaut
    Les traitements doivent être effectués dans le DoWork et non le RunWorkCompleted !

  12. #12
    Membre très actif
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2010
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2010
    Messages : 237
    Par défaut
    ben vous m'avez dis de les placez dans le RUNWORKE.. pour éviter l'erreur que j'ai déjà posté

  13. #13
    Membre émérite
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2007
    Messages
    693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 693
    Par défaut
    La mise à jour des contrôles ne peuvent pas être effectués dans le doWork, il faut le faire par exemple dans le RunWorkCompleted qui lui s'exécute dans le thread appelant du backgroundworker
    Où ai-je dit de mettre les traitements dans le RunWorkerCompleted ? J'ai dit de mettre les opérations sur les contrôles dans le RunWorkerCompleted ou bien d'utiliser la méthode Invoke du contrôle pour faire les opérations dessus.

    En gros, je reprends, les traitements longs sont faits dans le DoWork, on transmet le résultat de ces traitements dans e.Result
    On récupère le résultat dans le RunWorkerCompleted dans le e.Result, et on traite ce résultat au niveau de l'affichage si nécessaire.

  14. #14
    Membre averti
    Inscrit en
    Octobre 2010
    Messages
    38
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 38
    Par défaut
    J'ai la même erreur que kensem à évoqué j'ai consulté le lien du Invoke et j'ai rien compris vous pouvez me donner un exemple avec le code de kensem pour mieu comprendre.

    Vous me sauverez en me donnant un exemple.

  15. #15
    Membre émérite
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2007
    Messages
    693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 693
    Par défaut
    Bon reprenons à partir d'un exemple simple (on oublie le Invoke pour simplifier) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void uneMethodeTresLongue()
    {
             int monResultatAAffichier;
     
             .....
             monResultatAAffichier = unCalculTresLong(); // unCalculTresLong est une méthode très longue à exécuter
             .....
     
             txtboxAffichantmonResultat.Text = monResultatAAffichier.ToString();
    }
    Cette méthode est appelée à la suite du clici sur un bouton nommée btnCalculTresLong :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    private void btnCalTresLong_Click(object sender, EventArg e)
    {
        uneMethodeTresLongue();
    }
    Là mon interface va souffrir de freeze.

    Je me dis je veux que le calcul très soit fait dans un autre thread, j'utilise donc le BackgroundWorker :
    1. Je change l'appel de uneMethodeTresLongue pour utiliser le backgroundworker :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    private void btnCalTresLong_Click(object sender, EventArg e)
    {
         BackgroundWorker worker = new BackgroundWorker();
         worker.DoWork += new DoWorkEventHandler(worker_DoWork);
         worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
         worker.RunWorkerAsync();
    }[/
    Dans worker_DoWork, je place mon traitement long :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    private void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        e.Result = unCalculTresLong();
    }
    Dans worker_RunWorkerCompleted, je mets à jour mon affichage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if(e.Error != null && !e.Cancelled)
        {
            txtboxAffichantmonResultat.Text = ((int)e.Result).ToString();
        }
    }
    Là, mon interface ne subit plus de freeze.

  16. #16
    Membre averti
    Inscrit en
    Octobre 2010
    Messages
    38
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 38
    Par défaut
    je peux mettre mes trois fonctions dans un seul bw_dowork?
    ou je dois créer pour chaque fonction un bw-dowork?

  17. #17
    Membre émérite
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2007
    Messages
    693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 693
    Par défaut
    Tu peux ! Mais cela dépend surtout de ce qu'elles font !

  18. #18
    Membre averti
    Inscrit en
    Octobre 2010
    Messages
    38
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 38
    Par défaut
    Voici mon code ,
    mais mon interface freeze toujours, pas d'erreurs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     private void buttonStart_Click(object sender, EventArgs e)
            {
                if (bw.IsBusy != true)
                {
                    bw.RunWorkerAsync();
                }
                else { MessageBox.Show("waittt"); }
            }
     
            private void bw_DoWork(object sender, DoWorkEventArgs e)
            {
                BackgroundWorker worker = sender as BackgroundWorker;
     
                for (int i = 1; (i <= 10); i++)
                {
     
     
                    if ((worker.CancellationPending == true))
                    {
                        e.Cancel = true;
                        break;
                    }
                    else
                    {
     
     
     
                 chart17_Click();
     
                    }
                }
            }
            private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                if ((e.Cancelled == true))
                {
                    this.Text = "Canceled!";
                }
     
                else if (!(e.Error == null))
                {
                    this.Text = ("Error: " + e.Error.Message);
                }
     
                else
                {
     
                    chart17_Click();
                }
            }

  19. #19
    Membre émérite
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2007
    Messages
    693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 693
    Par défaut
    Peux-tu m'expliquer la présence du code en rouge souligné italique et gras là dedans :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
      private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                if ((e.Cancelled == true))
                {
                    this.Text = "Canceled!";
                }
     
                else if (!(e.Error == null))
                {
                    this.Text = ("Error: " + e.Error.Message);
                }
     
                else
                {
                   
                    chart17_Click();
                }
            }

  20. #20
    Membre averti
    Inscrit en
    Octobre 2010
    Messages
    38
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 38
    Par défaut
    c'es un long calcul qui me permet à la fin de remplir un champs et de tracer une courbe.
    Voici le code si vous êtes intéresse à le voir:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
     
     
                    chart3.Series[0].Points.Clear();
                    //valeur calcul
                    double W2;
                    double Fin = double.Parse(richTextBox92.Text);
                    double W0 = double.Parse(richTextBox6.Text);
                    double Pasdetemps = double.Parse(richTextBox54.Text);
                    double J = double.Parse(richTextBox3.Text) * 250;
                    double Couple;
     
                        double[,] Tab = new double[4,40000];
                        double W = W0;
                        double Temps = 0;
     
                        for (int i = 1; i <= 4000; i++)
                        {
     
                        Tab[1, i] = Temps;
                        Tab[2, i] = W * 30 / Math.PI;
     
                            Temps = Temps + Pasdetemps;
                            Couple = double.Parse(richTextBox148.Text) * Math.Pow(W, 2) + double.Parse(richTextBox149.Text) * W + double.Parse(richTextBox146.Text) * Math.Pow(W, 0.5) + double.Parse(richTextBox147.Text);
                            W2 = W + ((Couple * Pasdetemps) / J);
                            double Diff = W - W2;
     
                                 Tab[1, i+1] = Temps;
                                 Tab[2, i+1] = W * 30 / Math.PI;
                            if (Diff < Fin)
                            {
                                Tab[1, i + 2] = Temps;
                                Tab[2, i + 2] = W * 30 / Math.PI;
                            }
                            if (W < Fin)
                            {
                                Tab[1, i + 3] = Temps + Pasdetemps;
                                Tab[2, i + 3] = 0;
     
                            }
     
                            W = W2;
     
                            chart3.Series[0].Points.AddXY(Tab[1, i], Tab[2, i]);
     
                            richTextBox214.Text = Tab[2, i] > double.Parse(richTextBox92.Text) ? ">Max time" : Tab[1, i].ToString();
     
                    }
     
              }

Discussions similaires

  1. [Débutant] utilisation de BackgroundWorker
    Par geekploy dans le forum VB.NET
    Réponses: 4
    Dernier message: 15/01/2014, 00h35
  2. Comment utiliser un backgroundworker (vb.net 2005) ?
    Par Aspic dans le forum Contribuez
    Réponses: 1
    Dernier message: 23/04/2013, 17h22
  3. Exemple d'utilisation du BackgroundWorker
    Par infosam76 dans le forum Contribuez
    Réponses: 0
    Dernier message: 06/12/2012, 22h15
  4. Utilisation du BackgroundWorker
    Par jlm22 dans le forum VB.NET
    Réponses: 12
    Dernier message: 15/04/2011, 16h13

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