it-swarm.com.de

Wie verwende ich WinForms Fortschrittsbalken?

Ich möchte den Fortschritt von Berechnungen zeigen, die in einer externen Bibliothek durchgeführt werden.

Wenn ich zum Beispiel eine Berechnungsmethode habe und diese für 100000 Werte in meiner Form-Klasse verwenden möchte, kann ich schreiben:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }            

    private void Caluculate(int i)
    {
        double pow = Math.Pow(i, i);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        progressBar1.Maximum = 100000;
        progressBar1.Step = 1;

        for(int j = 0; j < 100000; j++)
        {
            Caluculate(j);
            progressBar1.PerformStep();
        }
    }
}

Ich sollte nach jeder Berechnung einen Schritt ausführen. Aber was ist, wenn ich alle 100000 Berechnungen in einer externen Methode durchführe? Wann sollte ich "Schritt ausführen", wenn ich diese Methode nicht von der Fortschrittsanzeige abhängig machen möchte? Ich kann zum Beispiel schreiben

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void CaluculateAll(System.Windows.Forms.ProgressBar progressBar)
    {
        progressBar.Maximum = 100000;
        progressBar.Step = 1;

        for(int j = 0; j < 100000; j++)
        {
            double pow = Math.Pow(j, j); //Calculation
            progressBar.PerformStep();
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        CaluculateAll(progressBar1);
    }
}

aber ich will das nicht so machen.

91
Dmytro

Ich würde vorschlagen, dass Sie einen Blick auf BackgroundWorker werfen. Wenn Sie eine so große Schleife in Ihrer WinForm haben, wird diese blockiert und Ihre App sieht aus, als hätte sie sich aufgehängt.

Schauen Sie sich BackgroundWorker.ReportProgress() an, um zu erfahren, wie der Fortschritt an den UI-Thread zurückgemeldet wird.

Zum Beispiel:

private void Calculate(int i)
{
    double pow = Math.Pow(i, i);
}

private void button1_Click(object sender, EventArgs e)
{
    progressBar1.Maximum = 100;
    progressBar1.Step = 1;
    progressBar1.Value = 0;
    backgroundWorker.RunWorkerAsync();
}

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    var backgroundWorker = sender as BackgroundWorker;
    for (int j = 0; j < 100000; j++)
    {
        Calculate(j);
        backgroundWorker.ReportProgress((j * 100) / 100000);
    }
}

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

private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // TODO: do something with final calculation.
}
109
Peter Ritchie

Seit .NET 4.5 können Sie eine Kombination aus asynchronem und erwarten mit Fortschritt zum Senden von Updates an den UI-Thread:

private void Calculate(int i)
{
    double pow = Math.Pow(i, i);
}

public void DoWork(IProgress<int> progress)
{
    // This method is executed in the context of
    // another thread (different than the main UI thread),
    // so use only thread-safe code
    for (int j = 0; j < 100000; j++)
    {
        Calculate(j);

        // Use progress to notify UI thread that progress has
        // changed
        if (progress != null)
            progress.Report((j + 1) * 100 / 100000);
    }
}

private async void button1_Click(object sender, EventArgs e)
{
    progressBar1.Maximum = 100;
    progressBar1.Step = 1;

    var progress = new Progress<int>(v =>
    {
        // This lambda is executed in context of UI thread,
        // so it can safely update form controls
        progressBar1.Value = v;
    });

    // Run operation in another thread
    await Task.Run(() => DoWork(progress));

    // TODO: Do something after all calculations
}

Aufgaben sind derzeit die bevorzugte Methode, um die Aufgaben von BackgroundWorker zu implementieren.

Aufgaben und Progress werden hier näher erläutert:

63
quasoft

Hey, es gibt ein nützliches Tutorial zu Dot Net-Perlen: http://www.dotnetperls.com/progressbar

In Übereinstimmung mit Peter müssen Sie eine gewisse Menge an Threading verwenden, oder das Programm bleibt einfach hängen, was den Zweck etwas zunichte macht.

Beispiel mit ProgressBar und BackgroundWorker: C #

using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, System.EventArgs e)
        {
            // Start the BackgroundWorker.
            backgroundWorker1.RunWorkerAsync();
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 1; i <= 100; i++)
            {
                // Wait 100 milliseconds.
                Thread.Sleep(100);
                // Report progress.
                backgroundWorker1.ReportProgress(i);
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            // Change the value of the ProgressBar to the BackgroundWorker progress.
            progressBar1.Value = e.ProgressPercentage;
            // Set the text.
            this.Text = e.ProgressPercentage.ToString();
        }
    }
} //closing here
2
Chong Ching