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 :

Thread et BackgroundWorker [Débutant]


Sujet :

C#

  1. #1
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2013
    Messages : 143
    Par défaut Thread et BackgroundWorker
    Bonjour,

    Je sais qu'il s'agit d'un sujet récurent et j'ai pu voir plusieurs post à ce sujet ici et ailleurs (stackoverflow) mais je reste quand même bloqué.

    Dans mon application (Winform) j'ai un bouton refresh qui permet de mettre à jour les données de mon Datagridview depuis ma base de données. Pour cela, j'ai voulu afficher une seconde form avec une progressbar qui se met en superposition de la form principale.
    Pour mettre en place cela j'ai vu sur des forums que je pouvais utiliser un BackgroundWorker pour gérer le traitement de mise à jour et la progression de ma progressbar dans ma second form.
    Après avoir suivi des exemples, le DoWork s'arrêtait après la première instruction de ma fonction RefreshData(). J'ai vite compris que je recevais une exception mais qui ne s'affichait pas. Grâce à internet j'ai pu régler ce soucis et afficher l'erreur.

    Cependant, une fois l'exception bien visible j'ai pu comprendre que j'avais un problème de Thread.
    "Error : System.InvalidOperationException: Opération inter-threads non valide : le contrôle 'refresh_bnt' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé...."

    De ce que j'ai pu comprendre en cherchant sur le net, il s'agit d'un soucis entre le thread principale de l'UI et celui du BackroundWorker. J'avoue que je suis pas vraiment familier avec la notion de Thread (et je devrais peut-être). J'ai cherché comment je pouvais régler ce problème et c'est là que je bloque.
    Tout ce que j'ai vu, proposent des solutions différentes (utiliser des Invoke, ajouter en paramètre le sender du DoWork dans la fonction etc...).

    C'est pour ça que je me suis décidé à demander de l'aide concernant mon cas pour mieux comprendre. Je vous mets ci-dessous la structure de mon code et vous remercie par avance pour vos retours

    NB : mon backroundworker se trouve dans la Form1 (principale) avec la propriété "WorkerReportsProgress" à true

    Form1
    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
    51
    52
     
    private FormBackgroundWorker frmPgBar = new FormBackgroundWorker(); // Form2
    private bool DoWork = false;
     
    private void refresh_btn_Click(object sender, EventArgs e)
    {
    	DoWork = true;
     
    	backgroundWorker1.RunWorkerAsync();
     
    	frmPgBar.ShowDialog();
    }
     
    private void RefreshData()
    {
    	// Traitement :
    	// Mise à jour de la BDD
    	// Actualisation du DatagridView
    	// Appel dans différentes partie du code de :
    	// backgroundWorker1.ReportProgress(nombre); // nombre : avancement que je donne au fur et à mesure
     
    	DoWork = false;
    }
     
    private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
    	RefreshData();
    }
     
    private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
    {
    	// update the ProgressBar in frmPgBar
    	frmPgBar.SetProgressBarValue(e.ProgressPercentage);
    }
     
    private void backgroundWorker1_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
    {
    	if (e.Error != null)
    	{
    		// You have an exception, which you can examine through the e.Error property.
    		MessageBox.Show("Error : " + e.Error.ToString());
    	}
    	else
    	{
    		// No exception in DoWork.
    		if (!DoWork)
    		{
    			frmPgBar.Close();
    			backgroundWorker1.ReportProgress(0);
    		}
    	}
    }
    Form2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    public void SetProgressBarValue(int pbValue)
    {
        progressBar1.Value = pbValue;
        this.pourcentage_lb.Text = pbValue.ToString() + "%";
    }

  2. #2
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2013
    Messages : 143
    Par défaut
    C'est bon, j'ai pu régler mon problème.

    Je post ma solution si jamais ça peut aider

    En gros dans ma fonction principale j'appelais d'autres fonctions qui faisaient du traitement sur l'interface de la Form1. Du coup, j'ai créé un delegate pour chaque fonctions qui touchent à l'UI et au lieu d'appeler directement ces fonctions je fais un Invoke.

    Exemple :

    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
     
    private delegate void EnabledControl_CB(bool value);
     
    private void EnabledControl(bool value)
    {
                this.refresh_btn.Enabled            = value;
                this.date_dtp.Enabled                = value;
                this.layoutFilter_tlp.Enabled       = value;
    }
     
    private void RefreshData()
    {
          this.Invoke(new EnabledControl_CB(EnabledControl ), new object[] { false });
     
          // Reste du code...
    }

  3. #3
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Ce n'est pas comme ça qu'il faut faire avec le BackgroundWorker. Tu attaches ta requête au DoWork et celle-ci sera exécutée sur un Thread en tâche de fond. Mais tu dispose aussi des événements ProgressChanged et RunWorkerCompleted ; une méthode attachée à l'un de ces événements sera exécutée sur le Thread du BackgroundWorker, c.à.d dans ton cas au Thread de l'UI. ProgessChanged sert à envoyer des notifications en cours de traitement (mettre WorkerSupportsCancellation à true auparavant) par un appel à ReportProgress() dans la méthode du DoWork ; RunWorkerCompleted est appelée à la fin du traitement, qu'il ait été mené au bout, ai été annulé ou ait échoucé (levée d'une Exception). C'est le backgroundWrker qui s'occupe de gérer la synchronisation des Thread de façon transparent pour l'utilisateur afin justement d'éviter des Invoke().

  4. #4
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2013
    Messages : 143
    Par défaut
    Bonjour,

    Merci pour ton retour

    Que veux-tu dire par attacher ma requête au DoWork ?

  5. #5
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Ce que tu as déjà fait : créer une méhode pour exécuter le travail en tâche de fond et l'ajouter à l'événement DoWork de ton BackgroundWorker.

  6. #6
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2013
    Messages : 143
    Par défaut
    Justement, en mettant ma fonction RefreshData() dans le DoWork() sans les Invoke() dans le RefreshData() pour les parties qui touche l'UI ça ne marche pas.

  7. #7
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    C'est normal, RefreshData est invoqué depuis le DoWork et c'est justement ce qu'il ne faut pas faire. Dans le DoWork tu appelles ReportProgess et dans ProgressChanged tu appelles RefreshData. Et dans RunWorkerCompleted tu ne dois pas appeler ProgressChanged, puisque cet événement sert à la notifier d'une évolution du travail en cours alors que celui-ci est justement censé être terminé quand tu arrives dans RunWorkerCompleted.

  8. #8
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2013
    Messages : 143
    Par défaut
    D'accord. Donc, si je mets le ReportProgress dans le DoWork je n'aurai plus accès au "ProgressPercentage". Donc au lieu de faire mes ReportProgress un peu partout dans RefreshData, il va falloir que je mets à jour une variable progress (int) que je mettrais en argument de ma fonction SetProgressBarValue(progress).

    Du coup, en faisant ça j'enlève mes Invoke dans RefreshData mais il va me faire la même erreur quand je voudrais faire appel à SetProgressBarValue() qui se trouve dans la Form2.

  9. #9
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Tu n'avais pas parlé d'un Form2 jusque-là. Mais si les deux Forms sont sur le même Thread il n'y a pas de raison qu'il y ait de problème.

  10. #10
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2013
    Messages : 143
    Par défaut
    J'en ai pas parlé explicitement mais j'en ai fais part dans mon premier message via le code.

    J'ai testé mais comme je le pensais il me fait la même erreur d'inter-thread sur ma fonction SetProgressBarValue de la Form2 que j'appel dans le DoWork de la Form1.

    Je ne sais pas vraiment comment le forcer à être sur le même thread que la form1, du coup j'ai quand même essayé de tester de faire un delegate de la fonction SetProgressBarValue dans la form2 pour l'appeler depuis la form1 avec un Invoke. Mais je me confronte à des difficultés en essayant de faire ça ^^'

  11. #11
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    J'ai fait un petit projet pour servir d'exemple. Il s'agit simplement d'un sélecteur de dossier qui en liste le contenu de façon récursive (il s'agissait de faire un exemple de traitement long). Tu peux le reproduire en créant un nouveau projet d'application WinForms et en collant la descrip le contenu des fichiers concernés. J'ai également fait un test en ouvrant une deuxième fenêtre à partir de la première et il n'y a aucun problème de synchronisation.

    FormExploreDirectory.cs :

    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    public partial class FormExploreDirectory : Form
        {
            public FormExploreDirectory()
            {
                InitializeComponent();
                btnCancel.Enabled = false;
                txtTemporization.Text = 10.ToString();
            }
     
            private BackgroundWorker _bw;
     
            private void btnSelect_Click(object sender, EventArgs e)
            {
                using (var dialog = new FolderBrowserDialog
                {
                    SelectedPath = !string.IsNullOrEmpty(txtPath.Text) ? txtPath.Text : @"C:\"
                })
                {
                    var result = dialog.ShowDialog();
                    if (result == DialogResult.OK)
                    {
                        txtPath.Text = dialog.SelectedPath;
                    }
                }
            }
     
            private void btnStart_Click(object sender, EventArgs e)
            {
                txtTemporization.Enabled = false;
                txtPath.Enabled = false;
                btnSelect.Enabled = true;
                btnStart.Enabled = false;
     
                _bw = new BackgroundWorker
                {
                    WorkerReportsProgress = true,
                    WorkerSupportsCancellation = true
                };
     
                _bw.DoWork += Bw_DoWork;
                _bw.ProgressChanged += Bw_ProgressChanged;
                _bw.RunWorkerCompleted += Bw_RunWorkerCompleted;
     
                txtResult.Text = string.Empty;
     
                btnCancel.Enabled = true;
                var temporization = int.Parse(txtTemporization.Text);
                _bw.RunWorkerAsync((txtPath.Text, temporization));
            }
     
            private void Bw_DoWork(object sender, DoWorkEventArgs e)
            {
                var worker = (BackgroundWorker)sender;
                var (path, temporization) = ((string, int))e.Argument;
                using (var writer = new StreamWriter(File.OpenWrite("tmp.txt")))
                {
                    ExploreDirectory(path, temporization, worker, e, writer);
                }
            }
     
            private void ExploreDirectory(string path, int temporization, BackgroundWorker worker, DoWorkEventArgs e, TextWriter writer)
            {
                Thread.Sleep(temporization); // Temporisation pour ne pas surcharger l'ui de messages
                var files = Directory.GetFiles(path);
                var items = files.Prepend(path).ToArray();
                writer.WriteLine(string.Join(Environment.NewLine, items));
                worker.ReportProgress(0, items);
     
                var directories = Directory.GetDirectories(path);
                foreach (var directory in directories)
                {
                    if (worker.CancellationPending)
                    {
                        e.Cancel = true;
                        return;
                    }
                    ExploreDirectory(directory, temporization, worker, e, writer);
                }
            }
     
            private void Bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                var items = (string[])e.UserState;
                txtResult.Text = string.Join(Environment.NewLine, items);
            }
     
            private void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                try { txtResult.Text = File.ReadAllText("tmp.txt"); }
                catch { }
     
                if (e.Cancelled)
                    MessageBox.Show("Vous avez annulé la recherche", "Action annullée", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                else if (e.Error != null)
                    MessageBox.Show(e.Error.Message, "Une erreur s'est produite", MessageBoxButtons.OK, MessageBoxIcon.Error);
                else
                    MessageBox.Show("La recherche est terminée", "Terminé", MessageBoxButtons.OK, MessageBoxIcon.Information);
     
                txtTemporization.Enabled = true;
                txtPath.Enabled = true;
                btnSelect.Enabled = true;
                btnStart.Enabled = true;
                btnCancel.Enabled = false;
            }
     
            private void btnCancel_Click(object sender, EventArgs e)
            {
                _bw.CancelAsync();
                btnCancel.Enabled = false;
                btnStart.Enabled = true;
                _bw = null;
            }
     
            private void txtTemporization_TextChanged(object sender, EventArgs e)
            {
                if (!int.TryParse(txtTemporization.Text, out int _))
                    txtTemporization.Text = 10.ToString();
            }
        }
    FormExploreDirectory.Designer.cs :

    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    partial class FormExploreDirectory
        {
            /// <summary>
            /// Variable nécessaire au concepteur.
            /// </summary>
            private System.ComponentModel.IContainer components = null;
     
            /// <summary>
            /// Nettoyage des ressources utilisées.
            /// </summary>
            /// <param name="disposing">true si les ressources managées doivent être supprimées*; sinon, false.</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
     
            #region Code généré par le Concepteur Windows Form
     
            /// <summary>
            /// Méthode requise pour la prise en charge du concepteur - ne modifiez pas
            /// le contenu de cette méthode avec l'éditeur de code.
            /// </summary>
            private void InitializeComponent()
            {
                this.btnStart = new System.Windows.Forms.Button();
                this.btnCancel = new System.Windows.Forms.Button();
                this.btnSelect = new System.Windows.Forms.Button();
                this.txtPath = new System.Windows.Forms.TextBox();
                this.txtResult = new System.Windows.Forms.TextBox();
                this.lblTemporization = new System.Windows.Forms.Label();
                this.txtTemporization = new System.Windows.Forms.TextBox();
                this.SuspendLayout();
                // 
                // btnStart
                // 
                this.btnStart.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
                this.btnStart.Location = new System.Drawing.Point(713, 415);
                this.btnStart.Name = "btnStart";
                this.btnStart.Size = new System.Drawing.Size(75, 23);
                this.btnStart.TabIndex = 0;
                this.btnStart.Text = "Démarrer";
                this.btnStart.UseVisualStyleBackColor = true;
                this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
                // 
                // btnCancel
                // 
                this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
                this.btnCancel.Location = new System.Drawing.Point(632, 415);
                this.btnCancel.Name = "btnCancel";
                this.btnCancel.Size = new System.Drawing.Size(75, 23);
                this.btnCancel.TabIndex = 1;
                this.btnCancel.Text = "Annuler";
                this.btnCancel.UseVisualStyleBackColor = true;
                this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
                // 
                // btnSelect
                // 
                this.btnSelect.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
                this.btnSelect.Location = new System.Drawing.Point(713, 9);
                this.btnSelect.Name = "btnSelect";
                this.btnSelect.Size = new System.Drawing.Size(75, 23);
                this.btnSelect.TabIndex = 2;
                this.btnSelect.Text = "Parcourir";
                this.btnSelect.UseVisualStyleBackColor = true;
                this.btnSelect.Click += new System.EventHandler(this.btnSelect_Click);
                // 
                // txtPath
                // 
                this.txtPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
                | System.Windows.Forms.AnchorStyles.Right)));
                this.txtPath.Location = new System.Drawing.Point(12, 12);
                this.txtPath.Name = "txtPath";
                this.txtPath.Size = new System.Drawing.Size(695, 20);
                this.txtPath.TabIndex = 3;
                // 
                // txtResult
                // 
                this.txtResult.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
                | System.Windows.Forms.AnchorStyles.Left) 
                | System.Windows.Forms.AnchorStyles.Right)));
                this.txtResult.Location = new System.Drawing.Point(12, 38);
                this.txtResult.Multiline = true;
                this.txtResult.Name = "txtResult";
                this.txtResult.ReadOnly = true;
                this.txtResult.ScrollBars = System.Windows.Forms.ScrollBars.Both;
                this.txtResult.Size = new System.Drawing.Size(776, 371);
                this.txtResult.TabIndex = 4;
                // 
                // lblTemporization
                // 
                this.lblTemporization.AutoSize = true;
                this.lblTemporization.Location = new System.Drawing.Point(12, 420);
                this.lblTemporization.Name = "lblTemporization";
                this.lblTemporization.Size = new System.Drawing.Size(165, 13);
                this.lblTemporization.TabIndex = 5;
                this.lblTemporization.Text = "Temporisation (en millisecondes) :";
                // 
                // txtTemporization
                // 
                this.txtTemporization.Location = new System.Drawing.Point(184, 418);
                this.txtTemporization.Name = "txtTemporization";
                this.txtTemporization.Size = new System.Drawing.Size(100, 20);
                this.txtTemporization.TabIndex = 6;
                this.txtTemporization.TextChanged += new System.EventHandler(this.txtTemporization_TextChanged);
                // 
                // FormExploreDirectory
                // 
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(800, 450);
                this.Controls.Add(this.txtTemporization);
                this.Controls.Add(this.lblTemporization);
                this.Controls.Add(this.txtResult);
                this.Controls.Add(this.txtPath);
                this.Controls.Add(this.btnSelect);
                this.Controls.Add(this.btnCancel);
                this.Controls.Add(this.btnStart);
                this.Name = "FormExploreDirectory";
                this.Text = "Contenu du dossier";
                this.ResumeLayout(false);
                this.PerformLayout();
     
            }
     
            #endregion
     
            private System.Windows.Forms.Button btnStart;
            private System.Windows.Forms.Button btnCancel;
            private System.Windows.Forms.Button btnSelect;
            private System.Windows.Forms.TextBox txtPath;
            private System.Windows.Forms.TextBox txtResult;
            private System.Windows.Forms.Label lblTemporization;
            private System.Windows.Forms.TextBox txtTemporization;
        }
    Edit : pourquoi je n'ai pas de coloration syntaxique sur mon code ?

  12. #12
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2013
    Messages : 143
    Par défaut
    Merci pour ton exemple

    J'ai essayé de le suivre mais du coup j'ai des questions ^^'

    Tu me disais qu'il fallait que je mette RefreshData() dans le ProgressChanged et faire les ReportProgess dans le DoWork. Le problème c'est que je fais mes ReportProgess dans ma fonction RefreshData() pour signaler que la valeur passe de 10 à 20 à 90% à tel ou tel niveau que le code est exécuté. Puis c'est ma fonction SetProgressBarValue() de ma form2 qui vient prendre "e.ProgressPercentage" de ProgressChanged pour mettre à jour la progressBar (qui se trouve dans ma Form2).

    Du coup si je dois obligatoirement mettre RefreshData() (qui s'occupe de traiter mes données BDD, dataset etc pour mon datagridview de la Form1) dans le ProgressChanged comment dans le DoWork je peux dire ReportProgess à 50% si je n'ai plus de traitement dedans ?

    J'ai vu que dans ton bouton Start tu avais mis des arguments dans le RunWorkerAsync()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    _bw.RunWorkerAsync((txtPath.Text, temporization));
    Qu'est-ce que ça fait de faire ça ?

    J'ai donc testé dans ton sens sans intervertir ce qu'il y avait dans le DoWork et le ProgressChanged (car je comprend pas comment faire (point plus haut)) et j'ai vu aussi que tu avais mis les modification UI avant de faire le RunWorkerAsync() et dans le RunWorkerCompleted. J'ai donc fait pareil mais le résultat est qu'il plante quand je fais appel à ma Form2 (showDialog) après le RunWorkerAsync().

    J'essaye d'être au plus clair dans mes explications car je t'avoue je suis un peu perdu en essayant de faire la bonne méthode sans passer par les Invoke ^^'

  13. #13
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Le paramètre DoWorkEventArgs possède une propriété Arguement, de type object. Quand tu invoque RunWorkerAsync avec un argument quelconque celui-ci sera inséré dans cette propriété afin d'être transmis à la méthode appelée (il faut faire un cast pour l'exploiter.

    Le point important à comprendre avec le BackgroundWorker c'est que la méthode invoquée par l'événement DoWork sera exécutés sur un Thread d'arrière plan et ne peut pas interagir directement avec l'UI ; les méthodes invoquées par ProgressChanged et RunWorkerCompleted en revanche sont exécutée sur le Thread d'origine du BackgroundWorker, c.à.d le Thread de l'UI et peut donc librement y faire appel. La méthode ReportProgress sert à faire la passerelle entre le deux Threads. Il est possible de lui passer un argument afin de transmettre des informations d'état au au ProgressChanged, via la propriété UserState du ProgressChangedEventArgs (là encore à récupérer avec un cast).

  14. #14
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Citation Envoyé par Nico1131 Voir le message
    J'essaye d'être au plus clair dans mes explications car je t'avoue je suis un peu perdu en essayant de faire la bonne méthode sans passer par les Invoke ^^'
    Après, en fonction de ton contexte (code de formation, code de production contraintes de temps ou bien de qualité) tu as le droit d'être pragmatique et si tu as trouvé une solution qui te convient avec des Invoke tu peux t'arrêter là. Mais de mon côté je me dois de te proposer une solution plus proche des standards et en principe plus propre dans la démarche (je ne prétend pas non plus détenir la vérité absolue).

  15. #15
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2013
    Messages : 143
    Par défaut
    Justement je suis ouvert aux propositions s'il y a des démarche plus propre que celle que j'ai pu faire

    Je comprend un peu mieux le fonctionnement des différents événements avec tes explication merci.

    Du coup grâce à toi je n'ai pas encore pu faire au plus propre mais j'ai quand même pu enlever deux des trois Invoke que j'avais fait donc c'est un bon début. Je vais laisser comme cela pour le moment vu que ça fonctionne mais dès que j'aurais un peu de temps libre j'essayerai de voir un peu plus en profondeur.

    Merci en tout cas pour ton aide. Si jamais je réussi sans faire mon Invoke je mettrai à jour mon post

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

Discussions similaires

  1. Réponses: 11
    Dernier message: 21/09/2015, 19h31
  2. Thread ou BackGroundWorker
    Par pradier4 dans le forum VB.NET
    Réponses: 3
    Dernier message: 26/08/2012, 14h42
  3. Executer le traitement dans un thread ou BackgroundWorker
    Par skunkies dans le forum Windows Forms
    Réponses: 13
    Dernier message: 28/05/2009, 23h41
  4. Réponses: 4
    Dernier message: 15/06/2007, 10h41
  5. [WinForms]BackgroundWorker et threads
    Par b4u dans le forum Général Dotnet
    Réponses: 2
    Dernier message: 13/12/2006, 18h55

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