While working with threads, one should be careful about UI Elements. Specially when we are working with BackgroundWorker thread. Here is an example which shows how to show a modal dialog from thread for displaying progress.
In this example, I have simply created two windows forms. The first form [Form1] has one button [button1]. button1 will show create a BackgroundWorker thread and launch it asynchronously. It uses method RunWorkerAsync of BackgroundWorker thread instance for this purposepublic partial class Form1 : Form{public Form1(){InitializeComponent();}BackgroundWorker worker;Form2 frm;private void button1_Click(object sender, EventArgs e){frm = new Form2();worker = new BackgroundWorker();worker.WorkerReportsProgress = true;worker.DoWork += new DoWorkEventHandler(worker_DoWork);worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);worker.RunWorkerAsync();frm.ShowDialog();}void worker_ProgressChanged(object sender, ProgressChangedEventArgs e){frm.ProgressValue = e.ProgressPercentage;}void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){frm.Close();MessageBox.Show("Done");}void worker_DoWork(object sender, DoWorkEventArgs e){CountTheTime();}private void CountTheTime(){int initialValue = 100;for (int count = 0; count < initialValue; count = count + 2){Thread.Sleep(1000);worker.ReportProgress(count);}}}
BackgroundWorker has three main events
- DoWork - will be fired when we launch the thread.
- RunWorkerCompleted - will fire when thread completes
- ProgressChanged - will fire when thread reports progress
and important property
- WorkerReportsProgress – should be set to True to enable progress reporting from a thread.
related method
- ReportProgress() – Reports progress back to the calling thread.
In aforementioned code, When we fire DoWork event by calling RunWorkerAsync method on worker thread. Eventhandler for this event will call the method CountTheTime() on the form.
CountTheTime() method intentionally put delay of 1 second. Here you can implement your time consuming code. We call ReportProgress() method on the thread to pass progress from this background thread to the main UI thread which holds our progress bar. This method will fire ProgressChanged Event
Then ProgressChanged eventhandler, worker_ProgressChanged updates the progressbar on Form2 with the help of ProgressValue property.public partial class Form2 : Form{public Form2(){InitializeComponent();}public int ProgressValue{get { return progressBar1.Value ; }set { progressBar1.Value = value; }}}
Conclusion:
Simple example of modal Progressbar with BackgroundWorker thread.
Hi,
ReplyDeleteBut my situation is different: What if I want to display the value of your int Count from CountTheTime()
in frm?
Benj
@Nunez, in worker_ProgressChanged event, we are already getting the value of count from e.ProgressPercentage. You can assign that value to your display control on the form.
ReplyDeleteThanks for an amazing tutorial, you rock!
ReplyDeleteHi,
ReplyDeleteI am getting Exception on (worker.ReportProgress(count);).....
"This BackgroundWorker states that it doesn't report progress. Modify WorkerReportsProgress to state that it does report progress.
@Ashu, Exception message is self explanatory. Please state it as below:
ReplyDeleteworker.WorkerReportsProgress = true;
if you haven't already done so.
Simple, elegant, and clear. Best resource I found on the subject.
ReplyDeleteThe Kettic Status Strip control is able to add progress bar to show state and operation progress.
ReplyDelete