0

我创建了一个backgroundWorker并且我在RunWorkerAsync之后调用InitializeComponent()但是在谷歌搜索并通过 Stack Overflow 之后,我知道我无法更新UI通过DoWork,我需要这样做RunWorkerCompleted

所以我正在这样做,但我的问题是我正在创建一个大数据表,DoWork以便我可以在我的网格中填充该数据RunWorkerCompleted,但是在执行所有操作后,当它进入RunWorkerCompleted我的应用程序时会挂起几秒钟,然后在加载后恢复。

我觉得这种情况正在发生,因为我正在获取大量数据,DoWork而当我RunWorkerCompleted用来显示这些数据时,它会挂起。

我从数据库中获取了大约 50,000 个数据。

如何解决这个问题。除了 BackgroundWorker我可以使用和做这些东西之外,还有什么办法吗?或者也许BackgroundWorker只有我可以做一些调整并且效果很好。

4

2 回答 2

0

抱歉,我知道这个线程很旧,但我遇到了类似的问题,并找到了一个不同的解决方案,不需要显式调用Invoke. 它基于这样一个事实,即ProgressChanged事件(几乎)通过报告某些内容来更新 UI,并且表明 BG-worker 没有被冻结或卡住。

确保你BackgroundWorker.WorkerReportsProgress=true并且还为事件添加了一个事件处理程序ProgressChanged

现在神奇的是,当您报告进度时,它采用百分比作为int(以及 type 的可选UserState参数object),但不会检查该值是否在任何特定范围内。因此,当我将进度报告为从0100的百分比时,进度会更新(例如完成 24%),但是当我发送超出该范围的数字时,会出现其他“更新”:

我的DoWork方法:

...
this._BG_Worker.ReportProgress(-1);
this._BG_Worker.ReportProgress(-2, "Reading NAND");
...
this._BG_Worker.ReportProgress((int)(100.0 * a / b), string.Format("{0}/{1} bytes", a, b));
...

我的ProgressChanged事件处理程序:

if (e.ProgressPercentage>=0 && e.ProgressPercentage<=100)
    this.tsslMain.Text=string.Format("{0}% done ({1})", e.ProgressPercentage, e.UserState);
else switch (e.ProgressPercentage)
{
    case -1:
        this.lbStatus.Items.Clear();
        break;
    case -2:
        if (e.UserState!=null && e.UserState is string)
            this.lbStatus.Items.Add(e.UserState as string);
        break;
    case ...
}

所以就在这里。

于 2015-02-24T17:45:19.270 回答
0

您绝对可以从DoWork方法内部更新 UI。您说您在评论部分遇到的错误是因为只有拥有控件的线程才被允许修改它。然而,其他线程也可以进行修改,但他们需要将其包装在委托中,这使得操作线程安全。在您的DoWork方法中,每当您想更新控件时,请遵循以下过程:

if (this.InvokeRequired)
{
  this.Invoke((MethodInvoker)delegate()
  {
     // Update the UI here. For example:
     // myTextBox.Text = "Hello World!";
  });
}
于 2013-05-11T05:50:54.707 回答