Execute code without a primary main lock

I need to generate n random strings, and this process may take some time and block the main thread interface. To avoid this and allow the user to use the program while running, I decided to use backGroundWorker . But this did not work, and the main thread is still blocked. In my DoWork event, I have something like this:

 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { // using Invoke because I change value of some controls, eg, ListView, labels and a progressbar this.Invoke((Action)delegate { for (int i = 0; i < nSteps; ++i) { string s = getnStr(); // ... int progress = (int)(100.0 / nSteps * (i + 1)); backgroundWorker1.ReportProgress(progress); } }); } 

Even if I call ReportProgress() inside the loop, the progress indicator only changes its value when the loop is complete.

Why is this happening and how can I fix it?

+5
source share
3 answers

Call ... That is where you fix it. You only create a background worker so that you call the code back into the main thread (which Invoke does).

In fact, you should either use the call only to access the controls, or change the controls only in the ReportProgress handler, and then every time you need it, you call the ReportProgress method.

EDIT: Clarification: your challenge with the call is that you are invoking a UI thread for the entire workload that the background was supposed to execute.

+9
source

Another answer explained the behavior you see. Please read it first. Here's how to fix it:

BackgroundWorker deprecated because now we have Task and await . It automates a lot. Your code should probably look like this:

  //In the button click handler: for (int i = 0; i < nSteps; ++i) { await DoSomeWorkAsync(); int progress = (int)(100.0 / nSteps * (i + 1)); SetProgressBarValue(progress); } 

That is really all. You must ensure that DoSomeWorkAsync not blocking. He must return a Task .

+3
source

In addition to the reporting process, the ReportProgress () method can be used as a general asynchronous event dispatcher (for example, to update text in user interface controls):

  for (int i = 0; i < nSteps; ++i) { string s = getnStr(); // Update text backgroundWorker1.ReportProgress(0, "My text.."); // Update progress int progress = (int)(100.0 / nSteps * (i + 1)); backgroundWorker1.ReportProgress(progress); } 

ProgressChanged event handler will look something like this:

 void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { if (e.UserState != null) { // Handle text update label1.Text = (string)e.UserState; return; } progressBar1.Value = e.ProgressPercentage; } 
+1
source

All Articles