如何使用WinForms进度条?

时间:2021-03-04 15:53:16

I want to show progress of calculations, which are performing in external library.

我想展示在外部库中执行的计算过程。

For example if I have some calculate method, and I want to use it for 100000 values in my Form class I can write:

例如,如果我有一些计算方法,我想用它来表示我的表单类中的100000个值,我可以写:

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();
        }
    }
}

I should perform step after each calculation. But what if I perform all 100000 calculations in external method. When should I "perform step" if I don't want to make this method dependant on progress bar? I can, for example, write

我应该在每次计算后执行步骤。但是如果我用外部方法来计算所有100000次。如果我不想让这个方法依赖于进度条,我应该在什么时候“执行步骤”?例如,我可以写作

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);
    }
}

but I don't want to do like that.

但我不想那样做。

3 个解决方案

#1


88  

I would suggest you have a look at BackgroundWorker. If you have a loop that large in your WinForm it will block and your app will look like it has hanged.

我建议你去看看背景工作人员。如果你的WinForm中有这么大的循环,它会阻塞,你的应用会看起来像挂起了一样。

Look at BackgroundWorker.ReportProgress() to see how to report progress back to the UI thread.

查看BackgroundWorker.ReportProgress(),了解如何向UI线程报告进度。

For example:

例如:

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.
}

#2


31  

Since .NET 4.5 you can use combination of async and await with Progress for sending updates to UI thread:

由于。net 4.5可以使用异步的组合,并等待向UI线程发送更新的进展:

private void Caluculate(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++)
    {
        Caluculate(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
}

Tasks are currently the preferred way to implement what BackgroundWorker does.

任务是实现BackgroundWorker所做事情的首选方式。

Tasks and Progress are explained in more detail here:

任务和进展在这里有更详细的解释:

#3


2  

Hey there's a useful tutorial on Dot Net pearls: http://www.dotnetperls.com/progressbar

嘿,有一个关于Dot Net pearl的有用教程:http://www.dotnetperls.com/progressbar

In agreement with Peter, you need to use some amount of threading or the program will just hang, somewhat defeating the purpose.

与Peter一致,您需要使用一些线程,否则程序就会挂起,这在一定程度上违背了目的。

Example that uses ProgressBar and BackgroundWorker: C#

使用ProgressBar和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

#1


88  

I would suggest you have a look at BackgroundWorker. If you have a loop that large in your WinForm it will block and your app will look like it has hanged.

我建议你去看看背景工作人员。如果你的WinForm中有这么大的循环,它会阻塞,你的应用会看起来像挂起了一样。

Look at BackgroundWorker.ReportProgress() to see how to report progress back to the UI thread.

查看BackgroundWorker.ReportProgress(),了解如何向UI线程报告进度。

For example:

例如:

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.
}

#2


31  

Since .NET 4.5 you can use combination of async and await with Progress for sending updates to UI thread:

由于。net 4.5可以使用异步的组合,并等待向UI线程发送更新的进展:

private void Caluculate(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++)
    {
        Caluculate(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
}

Tasks are currently the preferred way to implement what BackgroundWorker does.

任务是实现BackgroundWorker所做事情的首选方式。

Tasks and Progress are explained in more detail here:

任务和进展在这里有更详细的解释:

#3


2  

Hey there's a useful tutorial on Dot Net pearls: http://www.dotnetperls.com/progressbar

嘿,有一个关于Dot Net pearl的有用教程:http://www.dotnetperls.com/progressbar

In agreement with Peter, you need to use some amount of threading or the program will just hang, somewhat defeating the purpose.

与Peter一致,您需要使用一些线程,否则程序就会挂起,这在一定程度上违背了目的。

Example that uses ProgressBar and BackgroundWorker: C#

使用ProgressBar和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