Progress bar + thread [Résolu]

Messages postés
6
Date d'inscription
dimanche 13 décembre 2009
Dernière intervention
23 décembre 2009
- - Dernière réponse : cs_s7even
Messages postés
6
Date d'inscription
dimanche 13 décembre 2009
Dernière intervention
23 décembre 2009
- 23 déc. 2009 à 02:23
bonjour,

j'ai besoin de faire un form avec copie de répertoire + barre de progression pour l'avancement de la copie. Jusqu'ici tout va bien, ma progress bar avance comme il faut et la copie se passe sans problème.

J'ai voulu utiliser un thread pour la copie mais la ca coince car il y a conflit entre thread avec la progress bar

j'ai vu que je peux faire un Invoke sur la progress bar et j'ai essayé mais j'utilise un progressbar.PerformStep et je vois pas comment utiliser le Invoke

j'ai aussi vu que je peux utiliser un backgroundworker, je n'ai pas encore approfondi la dessus

donc j'aimerais votre avis, qu'est ce qui est le plus propre / rapide / stable ? Invoke ou backgroundworker ?


pour schématiser mon code, je débute la copie en utilisant un bouton du form

        private void button_start_Click(object sender, EventArgs e)
        {
            DirectoryInfo dvd = new DirectoryInfo(DVD);
// Taille du répertoire à copier -> taille max de la progressbar
            Int32 taille_tot = Convert.ToInt32(Taille_rep(dvd) / s7even_progress.MAIN.BufferSize);
            progressBar.Maximum = taille_tot;
// Thread qui appelle la méthode pour copier mes fichier
            ThreadStart thread_start = new ThreadStart(thread_copie);
            thread = new Thread(thread_start);
            label_etape.Text = "Copie des fichiers du DVD";
            thread.Start();
            label_etape.Text = "Copie terminée";
        }


Voici le code qui copie le repertoire et qui met la progress bar a jour

        public static void copie_DVD(string dvd, string rep_dest, ProgressBar progressBar)
        {
            try
            {
                DirectoryInfo rep = new DirectoryInfo(dvd);               
                    if (rep.Exists)
                    {
                        string vrai_rep_dest;
                        if (rep.Root.Name != rep.Name)
                        {
                            vrai_rep_dest = Path.Combine(rep_dest, rep.Name);
                            if (!Directory.Exists(vrai_rep_dest))
                            { Directory.CreateDirectory(vrai_rep_dest); }
                        }
                        else
                        { vrai_rep_dest = rep_dest; }
                        foreach (string d in Directory.GetDirectories(dvd))
                            Copie.copie_DVD(d, vrai_rep_dest, progressBar);
                        foreach (string fichier in Directory.GetFiles(dvd))
                        {
                            string fichier_dest = Path.Combine(vrai_rep_dest, Path.GetFileName(fichier));
                            Copie.copie_fichier(fichier, fichier_dest, progressBar);
                        }
                    }
                
            }
            catch (Exception)
            {
               MessageBox.Show(s7even_progress.erreur.affiche_erreur(03), "Erreur ... ", MessageBoxButtons.OK, MessageBoxIcon.Error);
               Application.Exit();
            }
        }
public static void step_progressbar(ProgressBar progressBar)
        {
            progressBar.PerformStep();
        }
        public static void copie_fichier(string f_a_copier, string f_de_destination, ProgressBar progressBar)
        {

            try
            {
                System.Diagnostics.Stopwatch stop = System.Diagnostics.Stopwatch.StartNew();
                using (FileStream inputStream = File.OpenRead(f_a_copier))
                {
                    using (FileStream outputStream = File.OpenWrite(f_de_destination))
                    {
                        byte[] bufferWork = new byte[s7even_progress.MAIN.BufferSize];
                        byte[] bufferLoad = new byte[s7even_progress.MAIN.BufferSize];
                        byte[] bufferTmp;
                        IAsyncResult asyncResult;

                        int nbRead = inputStream.Read(bufferWork, 0, bufferWork.Length);
                        while (nbRead > 0)
                        {
                            asyncResult = inputStream.BeginRead(bufferLoad, 0, bufferLoad.Length, null, null);
                            outputStream.Write(bufferWork, 0, nbRead);
                            nbRead = inputStream.EndRead(asyncResult);
                            
                            step_progressbar(progressBar);
                            
                            bufferTmp = bufferWork;
                            bufferWork = bufferLoad;
                            bufferLoad = bufferTmp;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString(), "erreur", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }



Je sais pas si c'est tres clair et propre je débute en c#, pour le moment ca marche sans le thread ce qui est déja pas mal vu mon niveau
si vous avez des conseils ou des critiques allez y
Afficher la suite 

Votre réponse

2 réponses

Meilleure réponse
Messages postés
142
Date d'inscription
mardi 27 novembre 2007
Dernière intervention
10 mai 2010
2
Merci
Salut,

Je n'ai jamais utilisé le backgroundworker, mais je peux t'aiguiller sur Invoke.
L'idée en multithread (j'en ai fait les frais!), c'est que si tu veux agir sur un composant qui appartient à un autre thread (ta ProgressBar), il faut "déléguer" l'ordre au thread qui en est propriétaire. Concrêtement, ta PBar appartient au thread principal (celui qui gère ton IHM). Si tu veux agir dessus depuis ton thread de traitement, il faut que tu envoies l'ordre au thread principal de le faire lui-même.

1- tu déclares un délégué qui va transmettre le message. Il doit avoir la même signature que la méthode que tu veux invoquer.
private delegate void DeleguePBar();


2- Dans ton thread (ici la méthode thread_copie), tu instancies un délégué qui pointera sur la méthode désirée. Il y a 2 façons de faire:
a- tu le fait pointer sur un méthode déclarée:
DeleguePBar oDlg = new DeleguePBAR(maMethode);

b- tu écris ta méthode "à la volée" (méthode anonyme). Quand tu veux juste appeler un refresh ou un PerformStep, pas besoin de déclarer une méthode qui ne fait qu'appeler une autre méthode!
DeleguePBar oDlg = delegate {this.progressBar.PerformStep();};


3- tu demandes au thread principal d'invoquer le délégué (toujours dans ton thread évidemment!):
this.Invoke(oDlg);


En gros, tu es le thread de traitement.. tu délègues quelqu'un pour aller dire au thread principal "exécute-moi ça s'teu plaît!".

NB: "this" représente l'instance de ton formulaire dans le thread principal. Je le précise parce que ça peut prêter à confusion puisque tout est dans la même classe.

Voilou, bon dev!

Si l'envie te prend de travailler, assied-toi et attend qu'elle te passe! (vieux -et faux!- dicton corse)

Merci JeremyLecouvert 2

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 101 internautes ce mois-ci

Commenter la réponse de JeremyLecouvert
Messages postés
6
Date d'inscription
dimanche 13 décembre 2009
Dernière intervention
23 décembre 2009
0
Merci
pfiou enfin réussi xD
du premier coup au dix septieme essai :p


merci a toi
Commenter la réponse de cs_s7even

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.