C#:尽管有BackgroundWorker,弹出窗体阻塞

时间:2010-08-19 09:22:40

标签: c# .net winforms user-interface backgroundworker

我正在使用.net 2.0,我创建了一个表单(System.Windows.Forms.Form),用于在长时间运行的任务中显示信息。

当我开始一个长时间运行的任务时,我创建了这个表单的新实例,调用.Show()并启动BackgroundWorker。但即使我使用BackgroundWorker来完成工作,表单确实显示出来,但是直接阻止并且直到后台工作者完成后才会响应,i.d。表单出现但内容(gif和文本框)未显示?

奇怪的是,当BackgroundWorker的工作密集时,这不会发生!?!怎么会?

示例:

private void UpdateReportingTab()
{
    //p is an instance variable; Progressbar is just a simple form control
    //showing the passed message
    p = new Progressbar("Loading Data...");
    p.Show();
    BackgroundWorker bw = new BackgroundWorker();
    bw.WorkerSupportsCancellation = true;
    bw.DoWork += new DoWorkEventHandler(bw_DoWork);
    bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
    bw.RunWorkerAsync();
}

private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{            
    p.BeginInvoke(new MethodInvoker(p.Close));
}

private void bw_DoWork(object sender, DoWorkEventArgs e)
{
    if (this.InvokeRequired)
    {
        this.BeginInvoke(new MethodInvoker(delegate()
        {
            //long running database queries, whose results update text fields
            //while text fields are filled p show "no response"
            TextEditItems.Text = Convert.ToString(itemsDao.getItemCount());
            ....
        }
    }
}

谢谢!

岸堤

2 个答案:

答案 0 :(得分:3)

因为你没有有效地运行后台工作人员,所以;)

后台工作人员进入主线程 - 将工作重新放入主UI线程中。

你不应该回想起你需要的东西。

特别地:

  • 进行长时间运行的数据库查询,检索结果
  • 然后调用回UI线程来更新TextEditItems

你回调的那一刻你回到了UI THREAD上 - 在你的情况下,后台工作者therad只会调用它...这会让后台工作者变得毫无意义。

答案 1 :(得分:2)

通过使用BeginInvoke,您实际上是在UI线程上执行代码。您的BackgroundWorker在这里没用,bw_DoWork将立即返回,用户界面将被冻结。

如果您需要控件中的某些数据,请在之前检索,然后启动BackgroundWorker,并在BGW线程上执行工作,而不是调用Invoke或{{ 1}}