Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use WinForms progress bar?

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:

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

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.

like image 926
Dmytro Avatar asked Aug 26 '12 00:08

Dmytro


People also ask

How do I use ProgressBar in Windows Forms?

To create a ProgressBar control at design-time, you simply drag a ProgressBar control from the Toolbox and drop onto a Form in Visual Studio. After you the drag and drop, a ProgressBar is created on the Form; for example the ProgressBar1 is added to the form and looks as in Figure 1.

How does ProgressBar work in C#?

A progress bar is a control that an application can use to indicate the progress of a lengthy operation such as calculating a complex result, downloading a large file from the Web etc. ProgressBar controls are used whenever an operation takes more than a short period of time.

Is WinForms obsolete?

Win Form has been used to develop many applications. Because of its high age (born in 2003), WinForm was officially declared dead by Microsoft in 2014. However, Win Form is still alive and well.


2 Answers

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.

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

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. } 
like image 66
Peter Ritchie Avatar answered Oct 16 '22 10:10

Peter Ritchie


Since .NET 4.5 you can use combination of async and await with Progress for sending updates to 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 } 

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

Tasks and Progress are explained in more detail here:

  • Async in 4.5: Enabling Progress and Cancellation in Async APIs
  • Reporting Progress from Async Tasks by Stephen Cleary
  • Task parallel library replacement for BackgroundWorker?
like image 41
quasoft Avatar answered Oct 16 '22 10:10

quasoft