Form的TextBox没有更新,但ProgressBar在ProgressChanged()中

时间:2014-12-30 12:31:59

标签: c# winforms backgroundworker

尝试更新更新的UI元素,DoWork()通过可视化进度条和提供当前值的文本框迭代DataTable中的每一行。迭代发生在后台工作程序中并按预期工作,进度条的PerformStep()也是如此。但是,TextBox的文本不会更改。

    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();
        }
    }

进度:

    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() + "%.";
        }
    }

呼叫者:

    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);
        }
    }

发生了什么:

enter image description here

我尝试了一些不同的东西,但没有一个能奏效。在ProgressChanged末尾添加另一个DoEvents()会导致堆栈溢出。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

你可以用你在这段代码中改变代码来包装你

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

答案 1 :(得分:0)

您可以从后台工作进行更新,而不是从主线程进行更新。此时,您的主线程仍在运行,并且不会处理您的更新。

除去

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

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

然后移动:

       progressBar.Hide();

到你的后台工作人员的结尾。并从代码中删除所有DoEvent。不需要进行更新。