7

这应该是一件相当简单的事情;但是,我一直无法弄清楚这一点。

/// This section is located in the InitializeComponent() method
/// form's class, i.e. partial class frmMain { .... }
this.bgw = new System.ComponentModel.BackgroundWorker();
this.bgw.WorkerReportsProgress = true;
this.bgw.DoWork += new System.ComponentModel.DoWorkEventHandler(this.bgw_DoWork);
this.bgw.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.bgw_ProgressChanged);

/// This code is located in public partial class frmMain : Form { .... }
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 1; i <= 100; i++)
    {
        Thread.Sleep(100); // Wait 100 milliseconds
        //Console.WriteLine(i);
        bgw.ReportProgress(i);
    }
}
private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // Update status label
    lblStatus.Text = e.ProgressPercentage.ToString();
}
// New code added to question after edit
public frmMain()
{
    InitializeComponent();
    bgw.RunWorkerAsync();
    // some more stuff...
}

后台工作人员运行正常;但是,它没有正确更新其进度。如果我取消注释 DoWork 事件中的注释行,我能够看到正确更新的状态;但是,在主线程中的任务(繁重的数据库计算内容)完成之后,才会触发 ProgressChanged 事件。

这是使用 .NET Framework 4 并且是 Windows 窗体应用程序。

编辑

有关代码所在的位置,请参见上述代码中的注释。

更多细节

正在执行的代码涉及在数据库上执行多个查询。我无权透露该代码。至于代码是如何执行的,我实际上不知道,因为另一个开发人员给了我一个 .dll,并被告知只能在访问数据库时使用它......

编辑

“一些更多的东西”部分中的代码被移动如下

private void frmMain_Load(object sender, EventArgs e)
{
   // some more stuff... aka run queries!
}
4

2 回答 2

4

你的BackgroundWorker代码很好。问题是您在其他地方(在这种情况下,在您的构造函数中FormLoad)有阻塞 UI 线程(通过执行同步数据库请求)的代码。您需要做一些事情来确保此代码在非 UI 线程中运行。这可能意味着使用这个现有的BackgroundWorker来执行那些其他长期运行的任务;它也可以通过使用Task.Factory.StartNew或其他一些线程机制让它在非 UI 线程中运行来完成。

一旦 UI 线程没有被阻塞,您将看到在 UI 中反映的 `ProgressChanged 事件处理程序中所做的更新。

于 2012-08-20T20:47:58.187 回答
2

@Servy 当然是正确的。

我只是想加入重现问题的代码:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        bgw.RunWorkerAsync();

        Task.Factory.StartNew(SomeMoreStuff);
    }

    private void SomeMoreStuff()
    {
        for (int i = 0; i < 5; i++)
        {
            Thread.Sleep(50);
            this.Invoke((Action)HogTheUIThread);
        }
    }

    private void HogTheUIThread()
    {
        Thread.Sleep(1000);
    }

    private void bgw_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i = 1; i <= 100; i++)
        {
            Thread.Sleep(100); // Wait 100 milliseconds
            //Console.WriteLine(i);
            bgw.ReportProgress(i);
        }
    }

    private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        // Update status label
        lblStatus.Text = e.ProgressPercentage.ToString();
    }
}
于 2012-08-20T21:06:44.597 回答