2013-05-11 68 views
0

我创建了一个backgroundWorker,我在Google上搜寻后然而,通过堆栈溢出调用InitializeComponent()RunWorkerAsync,我才知道,我无法通过DoWork我更新UI要做到这一点在RunWorkerCompletedBackgroundWorker的更新UI挂起​​由于大量的数据负载

所以我这样做,但我的问题是我创造的DoWork一个大的数据表,这样我可以通过RunWorkerCompleted填补我的网格数据,但这样做的一切之后,当它进入RunWorkerCompleted我应用程序挂起几秒钟,然后在加载后恢复。

我觉得这是发生的,因为我通过DoWork获取了很多数据,当我使用RunWorkerCompleted来显示它挂起的数据时。

我有大约50,000数据,我从数据库中提取。

如何解决此问题。也许我可以使用和做这些东西,除了BackgroundWorker还有什么办法。或者可能通过BackgroundWorker只有我可以做一些调整,它运作良好。

+0

为什么不能从'DoWork'更新UI? – PoweredByOrange 2013-05-11 05:31:41

+0

@ programmer93这是可能的。正如我那样做,它说'非法跨线程操作:控制'myTextBox'从一个线程访问,而不是它创建的线程。'我冲浪并知道不允许从'DoWork'更新UI更新 – 2013-05-11 05:41:37

+0

请参阅下面的答案。 – PoweredByOrange 2013-05-11 05:59:57

回答

0

您绝对可以从DoWork方法中更新UI。你说你在注释部分得到的错误是因为只有拥有控件的线程才允许修改它。但是,其他线程也可以进行修改,但它们需要将其包装在一个代理中,以使操作线程安全。在你DoWork方法,只要你想更新控制,遵循以下步骤:

if (this.InvokeRequired) 
{ 
    this.Invoke((MethodInvoker)delegate() 
    { 
    // Update the UI here. For example: 
    // myTextBox.Text = "Hello World!"; 
    }); 
} 
+0

我相信这仍然会阻止UI线程。也许如果他以更小的数据块添加数据,它将不太明显。不过,我可能会将记录数量限制在一个更易于管理的数量。 – JosephHirn 2013-05-11 06:29:14

+0

好的是,添加小块数据是关键。我不知道他使用的数据类型是什么,但是让我们说100个应该做​​的伎俩。无论如何,当工作完成时,它还是比一次提供UI的所有数据更好。 – PoweredByOrange 2013-05-11 06:32:28

+0

@ programmer93感谢您的回答,我只是试一试... – 2013-05-11 07:13:46

0

对不起,我知道这个线程是旧的,但我也有类似的问题,发现了不同的解决方案不要求对Invoke显式调用。它基于这样的事实,即ProgressChanged事件通过报告某种类型的指示BG工作人员未被冻结或卡住来更新UI(几乎)。

确保您的BackgroundWorker.WorkerReportsProgress=true并且还为ProgressChanged事件添加事件处理程序。

现在来的魔力,当你汇报进展,它需要一个百分比int(类型object的可选UserState参数一起),但不检查值是在任何特定的范围内。所以,当我汇报进度百分比从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 ... 
} 

所以这里。