SpaceSteak
SpaceSteak

Reputation: 199

Form's TextBox not updating, but ProgressBar is in ProgressChanged()

Trying to update a UI element that updates as DoWork() iterates through every line in a DataTable with a visual progress bar and a textbox that gives the current value. The iteration happens in a background worker and works as expected, as does the progress bar's PerformStep(). However, the TextBox's Text does not change.

    void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        table = SegmentationLibrary.Core.Utils.GetTableFromQuery(query);
        backgroundWorker1.ReportProgress(table.Rows.Count, "Max");
        int status = 0;
        backgroundWorker1.ReportProgress(status);
        table.Columns.Add("seg_rates_id", typeof(Int32));
        foreach (DataRow row in table.Rows)
        {
            row["seg_rates_id"] = 0;
            status++;
            backgroundWorker1.ReportProgress(status);
            Application.DoEvents();
        }
    }

Progress:

    void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        if (e.UserState != null && e.UserState.ToString() == "Max") {
            progressBar.progressBar1.Maximum = e.ProgressPercentage;
        }
        else if (e.ProgressPercentage == 0)
        {
            progressBar.progressBar1.Minimum = 0;
            progressBar.progressBar1.Style = ProgressBarStyle.Continuous;
            progressBar.progressBar1.Value = 1;
            progressBar.progressBar1.Step = 1;
            progressBar.tbProgress.Text = "Setting initial rate types";
        }
        else
        {
            progressBar.progressBar1.PerformStep();
            progressBar.tbProgress.Text = "Current at row " + progressBar.progressBar1.Value + " of " + progressBar.progressBar1.Maximum + ", " + progressBar.GetProgressBarPercent().ToString() + "%.";
        }
    }

Caller:

    public void GetFinacData(int year, int month)
    {
        if (!backgroundWorker1.IsBusy)
        {
            Application.EnableVisualStyles();
            currentMonth = month;
            currentYear = year;

            query = "SELECT * FROM FINAC_ACTUAL_DATA WHERE fiscal_year = " +
                currentYear + " AND fiscal_month = " + currentMonth + ";";
            progressBar.Show();
            progressBar.progressBarStyle = ProgressBarStyle.Marquee;
            progressBar.tbProgress.Text = "Downloading PSGL Extract from database";
            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
            backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
            backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
            backgroundWorker1.RunWorkerAsync();

            // required for ProgressBar to update?
            while (backgroundWorker1.IsBusy)
                Application.DoEvents();

            workerCompleted.WaitOne();
            progressBar.Hide();
        }
        else
        {
            MessageBox.Show("Segmentation already in progress.","Error",MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

What's happening:

enter image description here

I tried a few different things, but none of them work. Adding another DoEvents() at the end of ProgressChanged causes a stack overflow. Any ideas?

Upvotes: 0

Views: 772

Answers (2)

user4373877
user4373877

Reputation:

you could wrap you ui changing code inside this code

this.Invoke(new Action(() => { /* ui changing code */ }));

Upvotes: 1

Peter
Peter

Reputation: 27944

You can do the updating from the background work, not from your main thread. At this point your main thread is still working and your updates are not processed.

remove

        // required for ProgressBar to update?
        while (backgroundWorker1.IsBusy)
            Application.DoEvents();

        workerCompleted.WaitOne();
        progressBar.Hide();

then move the:

       progressBar.Hide();

to the end of your background worker. And remove all DoEvents from your code. It is not needed to do the updates.

Upvotes: 0

Related Questions