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 :

ProgressBar lancée en retard


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné
    Femme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2009
    Messages
    339
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Marne (Champagne Ardenne)

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

    Informations forums :
    Inscription : Avril 2009
    Messages : 339
    Par défaut ProgressBar lancée en retard
    Bonjour

    J'ai dans mon appli une tâche assez lourde lancée lorsque l'on appuie sur un bouton.

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    private void commencer_Click_1(object sender, EventArgs e)
    {
       ...
       speechRecognitionEngine.LoadGrammar(magrammaire);
       ...
    }

    Cette tâche est "brute de décoffrage" : pas moyen de suivre son évolution, pas moyen d'en extraire un quelconque évenement, ni de la scinder en plusieurs partie. Elle dure environ 5 secondes (mais peu importe).

    Pour spécifier à l'utilisateur que la tâche est en cours, j'ai pensé à mettre en place une progressbar (en suivant ce tutoriel) :

    Code C# : 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
    private void LanceThreadProgress()
    {
       if (progressbarCharg.InvokeRequired)
       {
          progressbarCharg.Invoke(new progressbarChargInvokeHandler(Progress));
       }
                else Progress();                
    }
     
    private delegate void progressbarChargInvokeHandler();
     
    private void Progress()
    {
      while (progressbarCharg.Value < progressbarCharg.Maximum)
         progressbarCharg.Value++;
    }
     
    private void commencer_Click_1(object sender, EventArgs e)
    {
       thrProgress = new Thread(new ThreadStart(LanceThreadProgress));
       thrProgress.Start();
     
       speechRecognitionEngine.LoadGrammar(magrammaire);
       ... 
    }

    Pour l'instant, je ne cherche pas à caler le step de la progessbar sur le temps réel de chargement. C'est un autre problème.

    Le problème, c'est que dans tous les cas, l'incrémentation de la progressbar commence après le chargement de la grammaire, alors que mon thread est appelé avant.

    Est-ce que j'utilise bien le thread ?
    Existe-t-il un autre moyen de procéder ?

  2. #2
    Membre éprouvé Avatar de rakakabe
    Développeur informatique
    Inscrit en
    Août 2007
    Messages
    124
    Détails du profil
    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2007
    Messages : 124
    Par défaut
    Et si tu mets LoadGrammar() dans un autre thread au lieu du progressBar ?
    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
     
    private event EventHandler<EventArgs> TaskStart;
     
     
    void commencer_Click_1(...)
    {
       this.TaskStart += new EventHandler(DemarrerProgression);
      Thread th = new Thread(new ThreadStart(LancerLoadGrammar));
      th.Run();
    }
     
    void LancerLoadGrammar()
    {
       if(TaskStart != null)
          TaskStart(this, new EventArgs());
       speechRecognitionEngine.LoadGrammar(magrammaire);
    }
     
    // Cette methode est a ameliorer
    void DemarrerProgression()
    {
       progressBar.Step = 1;
       progressBar.Maximum = 10000000;
       progressBar.Start();
       Progress(); // ta methode progress
       progressBar.End();
      ....
    }
    .

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 206
    Par défaut
    J'ai déjà été confronté à ce problème et le moyen que j'ai trouvé à l'époque fut de créer une form dans laquelle j'exécutais un backgroundworker et via ce backgroundworker je parvenais à récupérer une configuration lourde en base de données (environ 15 secondes je crois me rappeler) et à mettre à jour simultanément une barre de progression.

    Je n'ai pas l'exemple de code sous la main, mais je pense que si tu cherches de ce côté là, tu devrais trouver ton bonheur.

    C'est pas forcément la meilleure des solutions bien sur,mais elle fonctionnais et fut rapidement implémentée.

    Je suis preneur d'une meilleur solution.

    Bon courage.

  4. #4
    Expert confirmé

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2006
    Messages
    3 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2006
    Messages : 3 580
    Par défaut
    salut

    le problème est simple

    Fait une fonction qui fait un while() ce que tu veux sur une IHM. En théorie, l'IHM n'est mise à jour que si tu sors de la fonction ou que si tu appelles Application.DoEvents() sinon, l'IHM ne se raffraichit pas

    T'as beau lancé un thread pour faire ta mise à jour, celà n'a pas de sens du fait de ce while... si tu insères un Application.DoEvents() tu auras "surement" un comportement plus proche de ce que tu veux !!!

  5. #5
    Membre chevronné
    Femme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2009
    Messages
    339
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Marne (Champagne Ardenne)

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

    Informations forums :
    Inscription : Avril 2009
    Messages : 339
    Par défaut
    Merci pour vos réponses rapides, je vais étudier un peu tout ça, et je reviendrai mettre la progression

  6. #6
    Membre chevronné
    Femme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2009
    Messages
    339
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Marne (Champagne Ardenne)

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

    Informations forums :
    Inscription : Avril 2009
    Messages : 339
    Par défaut
    Bien ! J'ai potassé tout ça, et je dois malheureusement dire que je n'obtiens toujours pas ce que j'attendais.



    Citation Envoyé par rakakabe Voir le message
    Et si tu mets LoadGrammar() dans un autre thread au lieu du progressBar ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
       this.TaskStart += new EventHandler(DemarrerProgression);
    Qu'est-ce que this.TaskStart ? Je n'ai pas compris comment l'implémenter...


    Citation Envoyé par kineton Voir le message
    J'ai déjà été confronté à ce problème et le moyen que j'ai trouvé à l'époque fut de créer une form dans laquelle j'exécutais un backgroundworker et via ce backgroundworker je parvenais à récupérer une configuration lourde en base de données (environ 15 secondes je crois me rappeler) et à mettre à jour simultanément une barre de progression.

    La solution du backgroundworker donne un résultat pas trop mal.

    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
    class Donnees
    {
       public SpeechRecognitionEngine sre;
       public Grammar gram;
       public ProgressBar pbar;
       public int taille;
       //constructeur
       public Donnees(SpeechRecognitionEngine sre, Grammar C, ProgressBar bar, int sz)
          {
                    this.sre = sre;
                    gram = C;
                    pbar = bar;
                    taille = sz;
          }
    }
     
    private void commencer_Click_1(object sender, EventArgs e)
    {
       Donnees maDonnee = new Donnees(sre, gramCmd, gram_refPdt, gram_qte_condit, progressbarCharg, poids);
       backgroundWorker1.RunWorkerAsync(maDonnee);
       progressbarCharg.Visible = true;
       backgroundWorker1.RunWorkerCompleted += new    RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
    }
     
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
       BackgroundWorker worker = sender as BackgroundWorker;
       Donnees d = e.Argument as Donnees;
       MessageBox.Show("dowork ! ");
       d.sre.LoadGrammar(gram);  //traitement lourd de 5 sec
       MessageBox.Show("done !");
       e.Result = d;
    }
     
    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
       Donnees d = e.Result as Donnees;
       d.pbar.Visible = false;
       MessageBox.Show("progress finie");
    }
    Comme ça, tout se passe bien : ma progressbar étant de style 'Masquee', elle apparait bien avant le traitement lourd, et elle s'anime correctement.

    Le problème, c'est que lorsque j'enlève la MsgBox

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MessageBox.Show("dowork ! ");
    Le problème réapparait...
    A savoir, la progressbar apparait bien, mais ne s'anime pas tant que le traitement lourd n'est pas fini...

    C'est dommage parce que j'y étais presque ^^
    D'où cela peut-il venir ? Je soupçonne l'ordonnanceur CPU de choisir les tâches selon son bon vouloir ^^

    Quelqu'un a-t-il une idée précise de ce comportement ?


    Citation Envoyé par theMonz31 Voir le message
    Fait une fonction qui fait un while() ce que tu veux sur une IHM. En théorie, l'IHM n'est mise à jour que si tu sors de la fonction ou que si tu appelles Application.DoEvents() sinon, l'IHM ne se raffraichit pas

    T'as beau lancé un thread pour faire ta mise à jour, celà n'a pas de sens du fait de ce while... si tu insères un Application.DoEvents() tu auras "surement" un comportement plus proche de ce que tu veux !!!
    Je n'ai pas tellement compris ta solution. J'ai cherché comment implémenter Application.DeEvents() proprement, et une explication précise, mais je n'ai rien trouvé de très détaillé. De plus, dans certains posts, ta solution est dite "barbare", pas naturelle.

    Pourquoi dis-tu que l'IHM ne se rafraichit pas ? Dans mes premiers posts, lorsque j'utilisais un while pour incrémenter la progressbar, je voyais tout à fait la progression. Mais après le traitement lourd.

    Pourrais-tu me détailler le fond de ta pensée ?

  7. #7
    Membre chevronné
    Femme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2009
    Messages
    339
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Marne (Champagne Ardenne)

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

    Informations forums :
    Inscription : Avril 2009
    Messages : 339
    Par défaut
    Moké, en suivant les instructions de sovitec, un :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Application.DoEvents();
    à la place de :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MessageBox.Show("dowork ! ");
    Débloque tout.

    Un grand merci à tous

  8. #8
    Membre éprouvé Avatar de rakakabe
    Développeur informatique
    Inscrit en
    Août 2007
    Messages
    124
    Détails du profil
    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2007
    Messages : 124
    Par défaut
    Bien que t'as resolu ton probleme, je defends ma proposition () :

    Citation Envoyé par Isythiel Voir le message
    Qu'est-ce que this.TaskStart ? Je n'ai pas compris comment l'implémenter...
    voir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    private event EventHandler<EventArgs> TaskStart; (a mettre dans la meme classe, c'est un evenement)
    Et essaie de lire et de comprendre un peu le code en entier. Cet evenement sert a notifier le thread responsable de la mise a jour du progressBar que la tache lourde a commencee.
    Comme l'evenement est geree prioritairement, il est fort probable que progressBar se met a jour selon ton souhait en meme temps que le demarrage de la tache lourde. D'ailleurs, tu peux tres bien utiliser BackgroundWorker au lieu du Thread.

    Par ailleurs, l'interet de la tache lourde dans un nouveau thread et la progression pour la tache principale est que, dans le cas contraite, la tache lourde pourrait se terminer au moment ou le thread mettant a jour l'affichage vient d'etre cree (prendre en compte le temps de creation du thread, et la lourdeur de InvokeRequired).

  9. #9
    Membre chevronné
    Femme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2009
    Messages
    339
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Marne (Champagne Ardenne)

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

    Informations forums :
    Inscription : Avril 2009
    Messages : 339
    Par défaut
    Je te remercie, je mettrai ta proposition en œuvre lorsque j'aurai le temps d'optimiser mon application (et ainsi comparer les propositions).

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

Discussions similaires

  1. Fermer l'animation (swf/exe lancé depuis Windows)
    Par ZiZouJH dans le forum Flash
    Réponses: 3
    Dernier message: 14/01/2003, 10h00
  2. comment programmer une progressbar
    Par Choucas dans le forum Paradox
    Réponses: 3
    Dernier message: 13/11/2002, 11h07
  3. ProgressBar avec plusieurs procédures
    Par elifqaoui dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 08/09/2002, 18h03
  4. Couleur de ProgressBar
    Par benj63 dans le forum C++Builder
    Réponses: 7
    Dernier message: 04/07/2002, 17h33
  5. DirectX 6, un peu en retard ... :\
    Par multani dans le forum DirectX
    Réponses: 3
    Dernier message: 28/05/2002, 19h19

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