-1

I have a simple threaded program that is simply counting up. This process should take up all processor resources because it is such a long loop. I programmed it using a BackgroundWorker thread. So there should be two flows. The main program, and the background counter. However when the program runs, the application locks and the screen does not update. I tested it, and the UpdateStatus is being called with the incremented values. Why is the BackgroundWorker preventing events in the main program thread from executing?

I realize that I can include a Application.DoEvents(); but that would defeat the purpose of using a thread in the first place (allow multiple processes equal share). Why is the BackgroundWorker causing to main program thread to stop responding?

    int numTest1 = 0;
    public Form1()
    {
        InitializeComponent();
        _worker = new BackgroundWorker();
        _worker.WorkerReportsProgress = true;
        _worker.DoWork += TestCounter;
        _worker.ProgressChanged += UpdateStatus;
        _worker.RunWorkerCompleted += FinalUpdate;
    }


    private void btnStart_Click(object sender, EventArgs e)
    {
        _worker.RunWorkerAsync();
    }

    private void TestCounter(object sender, DoWorkEventArgs e)
    {
        for (int loopCount = 0; loopCount < 1000000000; loopCount++)
        {
            numTest1 += 1;
            _worker.ReportProgress(0);
        }
}

    private void UpdateStatus(object sender, ProgressChangedEventArgs e)
    {
        lblTestUpdate.Text = numTest1.ToString();
    }

    private void FinalUpdate(object sender, RunWorkerCompletedEventArgs e)
    {
        lblTestUpdate.Text = numTest1.ToString();
        lblTestResult.Text = "Done";
    }  
Scott Mooney
  • 167
  • 1
  • 1
  • 4
  • The first thing you need to do is move `int numTest1 = 0;` to the `DoWork` handler and add `var bgw = sender as BackgroundWorker;` on top of the method. Then see what `ReportProgress()` is used for. You could increment `numTest1` in the loop, then `bgw.ReportProgress(loopCount / 1000000000, numTest1);` (the first argument is the ProgressPercentage, the other is the UserState). In the loop, add `Thread.Sleep(1);`. After, `e.Result = numTest1;` In `UpdateStatus()` you'll then have `lblTestUpdate.Text = e.UserState.ToString();` and in `FinalUpdate()`, `lblTestUpdate.Text = e.Result.ToString();` – Jimi Feb 13 '21 at 11:10
  • Well, the correct ProgressPercentage would actually be `bgw.ReportProgress((int)(((double)numTest1 / 1000000000) * 100), numTest1);` Details :) – Jimi Feb 13 '21 at 11:17

1 Answers1

0

The line _worker.ReportProgress(0) floods the message loop with messages in such a massive scale, that the message loop is unable to process them in a timely manner. And all other UI related messages are lost in the same huge queue, so everything becomes stuck. You should consider reducing the rate at which you report progress to the UI thread.

As a side note be aware that the BackgroundWorker class is technologically obsolete. It has been fully superseded by the async/await technology.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104