C # Winform ProgressBar et BackgroundWorker

J’ai le problème suivant:

J’ai un formulaire nommé MainForm. J’ai une longue opération à avoir lieu sur ce formulaire.

Alors que cette longue opération est en cours, je dois en montrer un autre de ProgressForm nommé au-dessus de MainForm.

ProgressForm contient une barre de progression qui doit être mise à jour pendant la durée de l’opération.

Une fois l’opération longue terminée, ProgressForm doit être fermé automatiquement.

J’ai écrit le code suivant:

using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using System.Threading; namespace ClassLibrary { public class MyClass { public static ssortingng LongOperation() { Thread.Sleep(new TimeSpan(0,0,30)); return "HelloWorld"; } } } using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace BackgroungWorker__HelloWorld { public partial class ProgressForm : Form { public ProgressForm() { InitializeComponent(); } public ProgressBar ProgressBar { get { return this.progressBar1; } set { this.progressBar1 = value; } } } } using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using ClassLibrary; namespace BackgroungWorker__HelloWorld { public partial class MainForm : Form { ProgressForm f = new ProgressForm(); public MainForm() { InitializeComponent(); } int count = 0; private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { if (f != null) { f.ProgressBar.Value = e.ProgressPercentage; } ++count; } private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Cancelled) { MessageBox.Show("The task has been cancelled"); } else if (e.Error != null) { MessageBox.Show("Error. Details: " + (e.Error as Exception).ToSsortingng()); } else { MessageBox.Show("The task has been completed. Results: " + e.Result.ToSsortingng()); } } private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { if (f == null) { f = new ProgressForm(); } f.ShowDialog(); //backgroundWorker1.ReportProgress(100); MyClass.LongOperation(); f.Close(); } private void btnStart_Click(object sender, EventArgs e) { backgroundWorker1.RunWorkerAsync(); } private void btnCancel_Click(object sender, EventArgs e) { backgroundWorker1.CancelAsync(); this.Close(); } } } 

Je ne trouve pas de moyen de mettre à jour progressBar .

Où devrais-je placer backgroundWorker1.ReportProgress() et comment devrais-je appeler cela?

Je ne dois apporter aucune modification à MyClass car je ne sais pas ce qui se passera ni le temps MyClass pour effectuer l’opération dans cette couche de mon application.

Quelqu’un peut-il m’aider?

    Un problème est que vous dormez pendant 30 secondes. Normalement, vous appelez ReportProgress à différents moments de votre tâche de longue durée. Donc, pour illustrer cela, vous voudrez peut-être modifier votre code afin qu’il s’endorme pendant 1 seconde, mais 30 fois – en appelant ReportProgress chaque fin de sumil.

    Un autre problème est que vous montrez votre ProgressForm partir du fil d’arrière-plan. Vous devez le démarrer dans le thread d’ interface utilisateur , mais y associer l’événement ProgressChanged l’agent d’arrière-plan. Ensuite, lorsque l’agent d’arrière-plan fait rapport de la progression, le formulaire de progression est mis à jour.

    ReportProgress est la méthode à utiliser pour appeler votre méthode de travail. Cette méthode déclenche l’événement ‘ProgressChanged’.

    Dans votre formulaire, vous pouvez attacher un gestionnaire d’événements à l’événement ProgressChanged. Dans ce gestionnaire d’événements, vous pouvez modifier la position de la barre de progression. Vous pouvez également attacher un gestionnaire d’événements à l’événement RunWorkerCompleted et, à l’intérieur de celui-ci, vous pouvez fermer le formulaire contenant la barre de progression.

    Il convient de noter que vous devez définir

     backgroundWorker1.WorkerReportsProgress = true; 

    si vous voulez que l’agent d’arrière-plan lève l’événement ProgressChanged et

     backgroundWorker1.WorkerSupportsCancellation = true; 

    si vous souhaitez pouvoir annuler le thread de travail.

    Comme les autres l’ont dit, exécutez f.ShowDialog () dans votre thread d’interface utilisateur et utilisez ProgressChanged pour mettre à jour ProgressWindow.

    Pour que le ProgressForm se ferme automatiquement, dans backgroundWorker1_RunWorkerCompleted, appelez f.Close (); Cela signifie que la longue opération est terminée et que nous pouvons fermer la fenêtre.

    Ce qui est nécessaire ici, c’est de ne pas transmettre l’ensemble du formulaire principal à la classe, mais simplement l’instance de votre BackgroundWorker! Vous devez définir l’expéditeur en tant qu’agent d’arrière-plan de la manière suivante:

     private void bgWorker_DoWork(object sender DoWorkEventArgs e) { // Get the BackgroundWorker that raised this event BackgroundWorker worker = sender as BackgroundWorker; // And now you just send worker to whatever class you need like so: bgArgs args = e.Argument as bgArgs; MyClass objMyClass = new MyClass(); MyClass.MyMethod(strValue, args.Option, worker); // Do something based on return value. } 

    Et ensuite, dans votre MyClass.MyMethod() vous feriez les calculs de progression et souleveriez simplement l’ worker.ReportProgress(int percentage) pour mettre à jour la barre de progression ou tout autre élément de votre formulaire d’interface utilisateur principale!

    Cela devrait fonctionner parfaitement!

    Consultez cet article MSDN pour plus de détails, voir leur exemple Fibonacci. C’est ce qu’ils font, car CalculateFibonacci est une classe personnalisée qui envoie des mises à jour à l’interface utilisateur du formulaire principal.

    Voir MSDN BackgroundWorker Class pour plus de détails.