BackgroundWorker内的方法循环时更新进度条

本文关键字:更新 循环 方法 BackgroundWorker | 更新日期: 2023-09-27 18:25:56

首先是我的代码布局:

public partial class GUI : Form
{
    public GUI()
    {
        InitializeComponent();
    }
    private void GoButton_Click(object sender, EventArgs e)
    {
            backgroundWorker1.RunWorkerAsync();
    }
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        BigMethod bigMeth = new BigMethod();
        bigMeth.begin();
    }
    public void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar.Value = e.ProgressPercentage;
        progressBar.Refresh();
    }
    void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        MessageBox.Show("Done");
    }
}
public class BigMethod()
// If it matters, BigMethod() is in a separate .cs file in the same namespace
{
public void begin()
    {
for (; time <= 3600; time += T_STEP)       //  Running for 1 hour
        {
            //**********************************************
            //  DO FOR EACH TIMESTEP
            //**********************************************
            // Stuff
            //**********************************************
            //  Report back
            //**********************************************
            gui.backgroundWorker1.ReportProgress((int)(time / RUNTIME * 100));
            //gui.progressBar.Value = (int)(time / RUNTIME * 100);
            Thread.Sleep(100);
            timeCounter += T_STEP;
        }   // End Loop
}
}

因此,我在一个单独的类中有一个名为BigMethod()的方法,它包含一个非常大的数学密集型循环,大约需要15秒才能完成。现在我有一个按钮,它异步运行一个包含巨大BigMethod()的BackgroundWorker。据我所知,这运行得很好,该方法在不"崩溃"GUI的情况下完成了它应该做的事情。

问题是,progressBar没有刷新。(每次BigMethod()内的循环完成时,它都会重新计算进度并向backgroundWorker报告)。属性progressBar.Value更新良好,Debug.WriteLine(progressBar.Value)显示的正是它应该显示的值,0-100平滑增加,但实际progressBar不会移动,完成后也不会跳到100。

如果我剪切BigMethod并将其放置在_DoWork中,一切都会很好,但这不是一个选项,因为它会严重分割代码布局。

我能做些什么来解决这个问题?我已经尝试过progressBar.Refresh()和progressBar.Update(),但它们什么都不做。

正如你可能知道的,我对线程是全新的,所以这里可能有一些明显的东西我遗漏了,但我就是看不到。你如何从类之外的地方更新progressBar?

BackgroundWorker内的方法循环时更新进度条

backgroundWorker位于与GUI线程不同的线程上。您必须通过查看InvokeRequired来检查您是否在GUI线程上(http://msdn.microsoft.com/en-us/library/system.windows.forms.control.invokerequired.aspx)。如果没有,请通过调用Invoke()来调用GUI线程上的函数(http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx)。

这个代码片段应该可以完成任务。

public void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new Action<object, ProgressChangedEventArgs>(backgroundWork1_ProgressChanged), sender, e);
        return;
    }
    this.progressBar.Value = e.ProgressPercentage;
}