DotNetZip, Background Worker et ProgressBar

Fermé
Exorion - Modifié par Whismeril le 16/05/2015 à 23:39
 Exorion - 17 mai 2015 à 15:00
Salut tout le monde !

Petit souci ici, je ne sais pas comment attribuer l'avancement d'un unzip sur le ProgressChanged de mon BackgroundWorker.

Voici mon code :

private void DownloadGame_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
 // ...
 if (!bw_unzip.IsBusy)
        bw_unzip.RunWorkerAsync();
     else
        MessageBox.Show("Can't run the worker twice!");
}
 
private void bw_unzip_DoWork(object sender, DoWorkEventArgs e)
        {
            ZipFile zipFile = new ZipFile(MonZip);
            zipFile.ExtractAll(MonDossier);
            zipFile.Dispose();
            zipFile = null;
        }
private void bw_unzip_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            pb_main.Value = e.ProgressPercentage;
            lb_progress.Text = "Download Completed ! Installing... " + e.ProgressPercentage + "%";
            lb_progress.Refresh();
        }


Tout fonctionne niquel, le logiciel ne passe pas en mode "Ne repond pas" donc le BW fait bien sont taf cependant ma ProgressBar ne bouge pas d'un poil !

Un peu d'aide ?

Merci d'avance.

EDIT: Précision du langage dans la coloration syntaxique.
A voir également:

3 réponses

Whismeril Messages postés 19030 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 27 avril 2024 931
Modifié par Whismeril le 16/05/2015 à 23:49
Bonsoir, il faut plusieurs choses qu'on ne voit pas dans ton extrait de code:
  • que bw_unzip.ProgressChanged soit abonnée à l'événement ProgressChanged de bw_unzip
  • que dans la méthode DoWork, tu demandes le déclenchement de la progression avec bw_unzip.ReportProgress(mettre ici une valeur)


Malgré cela, il est possible que tu aies un problème interthread (ça arrive quand le backgroundworker est lancé par une classe qui n'est pas la form qui affiche la progressera), dans ce cas il te faudra ajouter un dispatcher

Modérer m'amène à intervenir dans de nombreux posts, mais les seuls langages que je connaisses sont le C# et un peu de VB. Pour vos codes pensez à la coloration.
Réponse trouvée ->Question Résolue
0
Etant Debutant en C#, je ne sais pas du tout ce qu'est un Dispatcher.
Sinon j'ai bien ajoute l'evenement dans mon MainForm.Designer.cs
Et pour finir tout le DoWork est la. Je suppose que ce que j'ai mis est la "Methode".

Encore desole, je ne connais pas encore bien le vocabulaire.

Apres je suppose avoir fait une erreur. Mon BackgroundWorker n'est pas genere directement dans le code, il est genere par le Designer. C'est un probleme ? Et j'ai bien entendu mis "true" pour WorkerReportProgress.

Est-il possible de m'expliquer comment fonctionne ReportProgress ? Quelle valeur dois-je mettre ?

Merci d'avance.
0
Whismeril Messages postés 19030 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 27 avril 2024 931
17 mai 2015 à 09:18
Bonjour,

alors de façon générale, ça n'est pas qu'une histoire de vocabulaire, mais bien de concept, la programmation objet n'a rien à voir avec la programmation procédurale, par conséquent, manipuler des méthodes, des événements et des propriétés (ou sous un autre nom pour un autre langage...) est la base pour des langages objets.
Je t'invite donc à commencer par la base, pour t'éviter de te retrouver face à un mur un jour.
Ce tuto (parmis d'autres) est bien
https://tahe.developpez.com/dotnet/csharp/


Pour ton problème voici un exemple
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i<1000000000;i++)//je compte de 0 à 999 999 999
            {
                //tous les 10000000, j'avance la progressbar
                if (i % 10000000 == 0) backgroundWorker1.ReportProgress(i / 10000000);
            }
        }

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

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            backgroundWorker1.ReportProgress(100);//à la fin du processus, je mets la progressbar à 100%
        }


Enfin pour voir ce que le designer à écrit à ta placent quand tu poses le backgroundworker sur la form, et ensuite que tu double-cliques sur les événements dans le panneau de propriété, cherche InitializeComponent, fais une clic-droit/Atteindre la définition, et tu verras tous le code, que tu peux faire à la main si nécessaire, qui affiche les contrôles, lie les méthodes à un événement, etc...
0
J'avais deja vu ce fichier, c'est d'ailleurs la que j'ai ajoute les events du BW.

Pour ce qui est du code que vous m'avez fournis, il ne fonctionne pas comme prevu car le ReportProgress apparait tout le temps, du coup les 99% sont atteints bien avant la fin du ExtractAll. Certains fichiers a extraire font 100 Mo comme d'autres font 35Go, du coup il me faut un vrai progress
0
Whismeril Messages postés 19030 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 27 avril 2024 931 > Exorion
17 mai 2015 à 14:05
Le code que je t'ai donné est un exemple qui fonctionne avec une boucle que j'ai arbitrairement choisie.
A toi de comprendre comment ça marche, et à l'adapter à ton besoin
0
J'ai reussi a trouver quelque chose qui fonctionne pas mal, et autrement. :

string SelectedItem = cb_gameslist.SelectedItem.ToString();
            worker.WorkerReportsProgress = true;
            worker.WorkerSupportsCancellation = true;
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
            worker.ProgressChanged += (o, ee) =>
            {
                pb_main.Value += 1;
                int Percent = pb_main.Value * 100 / pb_main.Maximum;
                lb_progress.Text = "Download Completed ! Installing... " + Percent + "%";
                lb_progress.Refresh();
                lb_speed.Text = pb_main.Value + " / " + pb_main.Maximum + " Files";
            };
            worker.DoWork += (o, ee) =>
            {
                using (ZipFile zip = ZipFile.Read(@"data\zips\" + FileFetch.GetIdByName(SelectedItem) + ".zip"))
                {
                    pb_main.Invoke((MethodInvoker)delegate
                    {
                        pb_main.Maximum = zip.Count;
                    });
                    foreach (ZipEntry file in zip)
                    {
                        file.Extract(@"data\games\" + FileFetch.GetIdByName(SelectedItem), ExtractExistingFileAction.OverwriteSilently);
                        worker.ReportProgress(1);
                    }
                }
            };
            while (worker.IsBusy)
            {
                button1.Text = "Busy !";
            }
            worker.RunWorkerAsync();


Seulement voila, une fois sur deux, le worker est deja utilise, pour une raison que je comprends pas parce que c'est le seul worker que j'utilise et je l'utilise uniquement pour unzip, du coup il n'est pas cense etre utilise.
D'ailleurs, ca fonctionne une fois sur deux...

EDIT: Précision du langage dans la coloration syntaxique.
0
Whismeril Messages postés 19030 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 27 avril 2024 931
17 mai 2015 à 14:52
Heu là je ne suis pas sûr, les invoke j'ai pas trop joué avec, mais pour ce que j'en sais ça te crée un autre thread. Du coup ton backgroungworker ne finit pas forcément quand tu le penses, enfin il me semble.

Pour cette ligne
string SelectedItem = cb_gameslist.SelectedItem.ToString();

si cb_gameslist est un combobox,
cb_gameslist.Text
devrait sufire
0
Je ne suis pas oblige d'utiliser l'invoke, je l'ai utilise ici uniquement pour pouvoir modifier le pb_main, car etant donne que ce n'est pas le meme thread, je ne peux pas le modifier (Si j'ai bien compris)
Une autre solution ?
0