Progress bar + thread

Résolu
cs_s7even Messages postés 6 Date d'inscription dimanche 13 décembre 2009 Statut Membre Dernière intervention 23 décembre 2009 - 20 déc. 2009 à 17:55
cs_s7even Messages postés 6 Date d'inscription dimanche 13 décembre 2009 Statut Membre 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
A voir également:

2 réponses

JeremyLecouvert Messages postés 139 Date d'inscription mardi 27 novembre 2007 Statut Membre Dernière intervention 10 mai 2010 2
21 déc. 2009 à 13:49
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)
2
Rejoignez-nous