Question basique : progressBar + Thread

Signaler
Messages postés
5
Date d'inscription
lundi 5 décembre 2011
Statut
Membre
Dernière intervention
21 août 2012
-
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
-
Salut à tous,

J'ai lu et suivit plusieurs conseils pour résoudre mon problème sur différents sites et forum. Cependant, bien que la solution soit sous mes yeux, ça ne marche pas...

Mon programme ouvre un fichier txt dans lequel je vais récupérer et traiter un bon nombre d'information. Ce fichier est généré automatiquement par une autre application. Le traitement est plutôt long et je souhaite afficher une progressBar afin d'informer l'utilisateur que l'application répond toujours.

J'ai créer une méthode de traitement gérer par le thread principal. Elle incrémente un entier (qui me permettra de remplir ma pgb) au fur et à mesure de son avancement. Parallèlement, j'ai créé un thread qui vient lire périodiquement la valeur de cet entier pour l'attribuer à progressBar1.Value. C'est tout con ...

Pour cela, je fais appel à la méthode Invoke :

        public void fct_CreatThread_Progress()
        {
            Thread_fct_Progress = new Thread(this.Thread_Progress);
            Thread_fct_Progress.Start();
        }

        private void Thread_Progress()
        {
            int i_Periode = 250; //ms
            TimeSpan DiagTimeSpan;
            DateTime TempsDepartDiag = new DateTime();

            do
            {
                DiagTimeSpan = DateTime.Now.Subtract(TempsDepartDiag);
                if ((i_Periode - DiagTimeSpan.Milliseconds) > 0)
                    Thread.Sleep(i_Periode - DiagTimeSpan.Milliseconds);
                TempsDepartDiag = DateTime.Now;

                if(this.progressBar1.InvokeRequired)
                    this.progressBar1.Invoke((Delegate)this.fct_MAJ_Value);
                else
                    this.progressBar1.Value = i_Progression;

            } while (this.progressBar1.Value < this.progressBar1.Maximum);
        }

        private void fct_MAJ_Value()
        {
            //i_Progression = entier incrémenté dans le Thread principal
            this.progressBar1.Value = i_Progression; 
        }


Seulement voila, une fois ce thread créé, il tente d'invoquer la méthode "fct_MAJ_Value", mais rien ne se passe. En Debug, en pas à pas détaillé, il semble que l'application soit perdue au moment de l'invocation...

Visuellement, la fenêtre où se situe ma pgb est affichée comme ne répondant plus (alors que le traitement de mes données continu).

Avez vous une idée d'où se situe mon problème ?

Merci,

A+

Bobogator.
A voir également:

7 réponses

Messages postés
14738
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
23 novembre 2020
148
Bonjour,

Essayes de mettre la variable en globale, puis d'utiliser un Timer pour le rafraichissement de la barre de progression, cela évitera un éventuel appel entre Thread.

---------------------------------------------------------------------
[list=ordered][*]Pour poser correctement une question et optimiser vos chances d'obtenir des réponses, pensez à lire le règlement CS, celui-ci pour bien poser votre question ou encore celui-ci pour les PFE et autres exercices.[*]Quand vous postez un code, merci d'utiliser la coloration syntaxique (3ième icône en partant de la droite : ).[*]En VB.NET pensez à activer Option Explicit et Option Strict (propriété du projet) et à retirer l'import automatique de l'espace de nom Microsoft.VisualBasic (onglet Références dans les propriétés du projet).[*]Si votre problème est résolu (et uniquement si c'est le cas), pensez à mettre "Réponse acceptée" sur le ou les messages qui vous ont aidés/list
---
Mon site
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
42
Salut

Pour un traitement asynchrone avec un affichage de la progression, tu peux regarder la classe BackgroundWorker.
Les événements tels que OnProgressChanged sont effectués dans le thread appelant, donc tu peux directement changer la valeur de ta progress bar.

Krimog : while (!(succeed = try())) ;
- Nous ne sommes pas des décodeurs ambulants. Le style SMS est prohibé. -
Messages postés
5
Date d'inscription
lundi 5 décembre 2011
Statut
Membre
Dernière intervention
21 août 2012

Hello,

Merci beaucoup pour vos réponses,

J'ai essayé d'utilisé un backgroundworker mais le problème est le même.

ma ligne "backgroundWorker1.ReportProgress(i);" est censé faire appel à l'event ProgressChanged. Si je place un point d'arrêt dans ma fonction event ProgressChanged, je me rend compte qu'elle n'est jamais appelé alors que le ReportProgress est bien exécuté.

J'ai vérifié qu'un simple projet windows form contenant un BW + une progressBar fonctionne. C'est le cas.

Finalement, je pense qu'un truc bloque lors de mon traitement.

Je compte insérer ce simple code sur plusieurs de mes fenêtres pour savoir si cela bloque en général ou juste pendant le traitement. Si quelqu'un à déjà été confronté à ce genre de problème, ou pense avoir une solution, je suis tout ouïe.

Merci

Bobogator.
Messages postés
5
Date d'inscription
lundi 5 décembre 2011
Statut
Membre
Dernière intervention
21 août 2012

Rectification : L'event ProgressChaged n'est appelé qu'à la fin, lorsque mon traitement est terminé.
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
42
- As tu bien mis le WorkerReportsProgress à true ?
- Fais tu bien un report progress entre 0 et 100 (et pas entre 0.0 et 1.0) ?

Krimog : while (!(succeed = try())) ;
- Nous ne sommes pas des décodeurs ambulants. Le style SMS est prohibé. -
Messages postés
5
Date d'inscription
lundi 5 décembre 2011
Statut
Membre
Dernière intervention
21 août 2012

La propriété WorkerReportsProgress est bien à true. Mon code est très simple (pour tester) :

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            int i = 0;
            while (i<100)
            {
                Thread.Sleep(150);

                i++;
                backgroundWorker1.ReportProgress(i);
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.progressBar1.Value = e.ProgressPercentage;
        }


J'ai remarqué une chose étrange. Une fois le traitement terminé (géré par le thread principal), je met en suspend le Thread pendant une seconde pour que l'utilisateur ait le temps de voir la progressBar pleine. Après ça, j'arrête le BW et je fais un Dispose() de ma fenêtre contenant la PGB et le BW. Ce n'est qu'après que l'évènement se produit (codé et exécuté dans la classe précédemment "Disposed"), 100 fois à la suite.

Je n'ai pas beaucoup d'expérience en matière de programmation OO, juste quelques connaissance que j'ai acquise à l'école qui m'ont permis de travailler sur ce premier projet en C#. Je dois avouer que je suis perdu ...

Merci,

Bobogator.
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
42
Ton code marche, chez moi.

Voici, pour être préci, le code complet de mon Form1 (au niveau du designer, il a juste une progressBar1) :

using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private BackgroundWorker backgroundWorker1;

        public Form1()
        {
            InitializeComponent();
            backgroundWorker1 = new BackgroundWorker();
            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
            backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
            backgroundWorker1.RunWorkerAsync();
        }

        void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.progressBar1.Value = e.ProgressPercentage;
        }

        void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            int i = 0;
            while (i < 100)
            {
                Thread.Sleep(150);
                i++;
                backgroundWorker1.ReportProgress(i);
            }

        }
    }
}


Krimog : while (!(succeed = try())) ;
- Nous ne sommes pas des décodeurs ambulants. Le style SMS est prohibé. -