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] Form ProgressBar qui ne bloque pas le traitement


Sujet :

C#

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 1 002
    Par défaut [Thread] Form ProgressBar qui ne bloque pas le traitement
    Bonjour,

    je suis en .NET 2.0 C#

    J'aimerai faire une petite classe générique qui permet de faire un truc somme toute classique: afficher les étapes d'un traitement en cours avec une barre de progression (progressbar)

    Comment m'y prendre pour que ca ne bloque pas le traitement qui tourne derrière ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
                using (StepForm f = new StepForm ())
                {
                    f.Show();
                 }
    je sais que Show permet de faire en sorte que ce soit non modal... mais après je ne sais pas comment réaliser le reste.
    Que me conseillez vous ? Quelle est la bonne pratique ?
    D'utiliser Invoke, un backgroundWorker ?

    Merci du coup de main & Bonne journée à tous

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 85
    Par défaut
    Utiliser les Threads est une bonne idée. Vous avez un exemple dans les tuto :
    http://drq.developpez.com/dotnet/articles/threads/#L5

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

    Informations forums :
    Inscription : Octobre 2007
    Messages : 1 002
    Par défaut
    rori
    Et bien c'était pile poil ce que je recherche !
    (j'ai du mal chercher)

    Je te remercie et je te souhaite de passer une agréable journée !

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 1 002
    Par défaut
    Hum par contre je souhaite mettre un bouton annuler dans ma Form ou il y a la progression, seulement celui si est "bloqué" pour le moment pendant la progression...

    Donc j'ai 2 form:
    Une principal qui appel la form de progression ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
                using (StepForm f = new StepForm ())
                {
                    f.Show();
                    int progression = 1;
                    while (f.GoToStep(progression) && progression < 100)
                    {
                        System.Threading.Thread.Sleep(50);
                        ++progression;
                    }
                    f.Close();
                }

    dans ma form de progression il y 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
        public partial class StepForm : Form
        {
     
            private delegate void ProgressBarDelegateHandler(int step);
            private ProgressBarDelegateHandler ProgressBarDelegate;
     
            public StepForm()
            {
                InitializeComponent();
     
                ProgressBarDelegate = new ProgressBarDelegateHandler(UpdateProgressBar);
            }
     
            private void UpdateProgressBar(int step)
            {
                progressBar1.Value = step;
            }
     
            public bool GoToStep(int progression)
            {
                this.Invoke(this.ProgressBarDelegate, new object[] { progression });
                this.Update();
                return true;
            }
        }

    EDIT/
    BeginInvoke ?

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 1 002
    Par défaut
    Arf j'ai essayé avec la methode BeginInvoke... mais le bouton est toujours bloqué....

    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
            private delegate void InvokeMethod(int step);
     
            public StepForm()
            {
                InitializeComponent();
     
            }
     
            private void UpdateProgressBar(int step)
            {
                progressBar1.Value = step;
            }
     
            public bool GoToStep(int progression)
            {
     
                IAsyncResult res = progressBar1.BeginInvoke(new InvokeMethod(UpdateProgressBar), new object[] { progression });
                progressBar1.EndInvoke(res);
                this.Update();
                return true;
            }

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 85
    Par défaut
    C'est normal, vous n'utilisez pas les Threads !

    Dans votre exemple, tout se fait sur le Thread de votre Main.

    Regarder bien dans le tutorial que je vous ai link :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Thread t = new Thread(new ThreadStart(ThreadProcess));
    t.Start();
     
    private void ThreadProcess() {
    	for(int i = 0 ; i < 11 ; i++) 
    	{
    	   // Déclenche la mise à jour de l'interface
    	   this.Invoke(this.ProgressBarDelegate,new object[] {i});
    	   Thread.Sleep(1000);
    	 }
    }
    Ici c'est bien un nouveau thread (t) qui gére la mise à jour de la ProgressBar.

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 1 002
    Par défaut
    Dans l'exemple il utilise tout depuis une meme form

    Moi j'ai 2 forms: la principale qui 'control' la seconde en lui indiquant à quelle étape elle en est...
    Bon j'ai essayé de threader l'appel sur la form principal:
    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
            private void TesterStepForm_Click(object sender, EventArgs e)
            {
                Thread t = new Thread(new ThreadStart(ThreadProcess));
                t.Start();
            }
     
            private void ThreadProcess()
            {
     
                using (ProgressBarEtapeForm f = new ProgressBarEtapeForm())
                {
                    f.Show();
                    int progression = 1;
                    while (progression < 100)
                    {
                        f.Invoke(f.ProgressBarDelegate, new object[] { progression });
                        System.Threading.Thread.Sleep(50);
                        ++progression;
                    }
                    f.Close();
                }
            }

    et sur la StepForm:
    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
            public bool GoToStep(int progression)
            {
     
                Thread t = new Thread(new ThreadStart(ThreadProcess));
                t.Start();
                return true;
     
            }
     
            private void ThreadProcess()
            {
                IAsyncResult res = progressBar1.BeginInvoke(new InvokeMethod(UpdateProgressBar));
                progressBar1.EndInvoke(res);
                this.Update();
            }
    bon jdois etre à coté de la plaque...


    :::: EDIT ::::
    // Là je suis un peu dans les choux niveau code, si c'est possible pourriez vous me dire à quel endroit il faut threader en reprenant mon précédent code

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 85
    Par défaut
    Voilà comment je m'y prendrai :

    - Votre "StepForm" qui contient la progressBar possède une méthode pour la mise à jour de sa ProgressBar

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public void UpdateProgressBar(int step)
    {
       progressBar1.Value = step;
    }
    - La Form principale :

    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
     
    public Form1()
    {
    	InitializeComponent();
    	f = new StepForm();
    	f.Show();
    	Thread t = new Thread(new ThreadStart(MyThread));
    	t.Start();
    }
     
    private void MyThread()
    {
    	for (int i = 0; i <= 100; i+= 10)
    	{
    		f.UpdateProgressBar(i);
    		Thread.Sleep(1000);
    	}
    }

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 1 002
    Par défaut
    rori Merci de ta patience & de ta réponse c'est sympa

    par contre:
    Opération inter-threads non valide : le contrôle 'progressBar1' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé.
    Avec ton code j'ai été obligé de mettre f en varibale d'instance !
    Peut on passer une variable à un thread ??
    typiquement un truc du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Thread t = new Thread(new ThreadStart(MyThread), f);

    ::: EDIT :::
    Jvais tester ca et je reviens:
    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
            static void Main(string[] args)
            {
                Thread th = new Thread(new ParameterizedThreadStart(Afficher));
     
                Thread th2 = new Thread(new ParameterizedThreadStart(Afficher));
     
                th.Start("A");
     
                //On attend la fin du thread A avant de commencer le thread B.
                th.Join();
     
                th2.Start("B");
     
                Console.ReadKey();
            }
     
            static void Afficher(object texte)
            {
                for (int i = 0; i < 10000; i++)
                {
                    Console.Write((string) texte);
                }
            }


    :::: EDIT2 ::::

    Erreur 1 Aucune surcharge pour 'MyThread' ne correspond au délégué 'System.Threading.ParameterizedThreadStart'
    je suis en 2.0


    ::: EDIT 3 :::

    J'ai rien dis il faut mettre object en param,
    mais j'ai toujours l'erreur:
    Opération inter-threads non valide : le contrôle 'progressBar1' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé.

  10. #10
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 1 002
    Par défaut
    Ok pour le moment j'ai un truc qui à l'air de fonctionner,
    jvais mettre au propre et le poster ici pour que vous me donniez votre avis d'ici peu

    Je te remercie rori pour ton aide précieuse!

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 85
    Par défaut
    Citation Envoyé par alavoler Voir le message

    ::: EDIT 3 :::

    J'ai rien dis il faut mettre object en param,
    mais j'ai toujours l'erreur:
    Opération inter-threads non valide : le contrôle 'progressBar1' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé.
    Il faut faire un Invoke() sur le delegué de la méthode qui met à jour la progresseBar

  12. #12
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 1 002
    Par défaut
    Bon je poste mon code, si quelqu'un peu me dire ce qu'il en pense (si ca vous parait coherent & élégant) je suis preneur

    La form qui appel ma form progress bar et qui lance un 'traitement':
    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
            private void TesterStepForm_Click(object sender, EventArgs e)
            {
     
                using (StepForm f = new StepForm())
                {
                    Thread t = new Thread(new ParameterizedThreadStart(MyThread));
                    t.Start(f);
                    if (f.ShowDialog() == DialogResult.OK)
                        MessageBox.Show("Operation OK");
                    else if (f.DialogResult == DialogResult.Cancel)
                        MessageBox.Show("Operation cancelled");
                }
            }
     
            private static void MyThread(object o)
            {
                StepForm f = (StepForm) o;
                for (int i = 0; i <= 100; ++i)
                {
                    f.GoToStep(i);
                    Thread.Sleep(20);
                }
                f.DialogResult = DialogResult.OK;
                f.Invalidate();
            }

    le code la form qui s'occupe de l'affichage des étapes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
            private void UpdateProgressBar(int step)
            {
                progressBar1.Value = step;
            }
     
            private delegate void MyProc<T>(T p1);
     
            public bool GoToStep(int progression)
            {
                if (InvokeRequired)
                    Invoke(new MyProc<int>(UpdateProgressBar), progression);
                return true;
            }
    Merci

  13. #13
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 1 002
    Par défaut
    re,

    sur mes Invoke parfois j'ai ce message quand je clic sur "Annuler" de ma StepForm:
    ObjectDisposedException
    Impossible d'accéder à un objet supprimé.
    J'ai cru dans un premier temps que le if (InvokeRequired) suffirait mais visiblement pas dans tous les cas !

    De plus j'ai parfois une certaine latence entre le moment ou je fais un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    f.DialogResult = DialogResult.OK;
    dans mon thread, et que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MessageBox.Show("Operation OK");
    s'affiche

  14. #14
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 1 002
    Par défaut
    Hum... pour l'effet de 'latence', en fait j'ai réussi à reproduire:
    Pour que MessageBox.Show("Operation OK") s'affiche, il faut que je bouge simplement la souris et la ca close l'ecran StepForm, et ca m'affiche bien la MsgBox....


    Donc si quequ'un peu relire mon code je suis preneur, je continue à chercher de mon coté, merci

  15. #15
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 1 002
    Par défaut
    Bon en mettant un f.Invalidate(); ca résout le problème du refresh (mais ca complique l'implémentation du coté des gens qui utilise ce pti composant StepForm !....)

    je suis toujours à la recherche d'un relecteur de code... // critique & co
    Et j'ai toujours mon problème de "Impossible d'accéder à un objet supprimé." sur mes invokes !




    je met à jours mon code 3 postes plus haut

Discussions similaires

  1. Temporisation qui ne bloque pas l'application
    Par Zorgloub dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 14/02/2008, 17h55
  2. Réponses: 4
    Dernier message: 04/01/2008, 12h44
  3. alert() qui ne bloque pas le chargement de la page ?
    Par Cofondinde dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 16/08/2007, 11h31
  4. recvfrom qui ne bloque pas ?
    Par innosang dans le forum Réseau
    Réponses: 1
    Dernier message: 21/06/2007, 12h11
  5. Réponses: 8
    Dernier message: 25/11/2005, 19h38

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