C# BackgroundWorker在RunWorkerCompleted上更新UI,但由于数据负载过大,系统挂起
我创建了一个C# BackgroundWorker在RunWorkerCompleted上更新UI,但由于数据负载过大,系统挂起,c#,.net,multithreading,gridview,backgroundworker,C#,.net,Multithreading,Gridview,Backgroundworker,我创建了一个backgroundWorker,在InitializeComponent()之后调用RunWorkerAsync,但是通过谷歌搜索和堆栈溢出,我知道我无法通过DoWork更新UI,我需要在RunWorkerCompleted中执行此操作 所以我这么做了,但我的问题是我在DoWork中创建了一个大数据表,这样我就可以通过RunWorkerCompleted将数据填充到我的网格中,但在完成所有操作后,当它转到RunWorkerCompleted时,我的应用程序会挂起几秒钟,然后在加载后
backgroundWorker
,在InitializeComponent()
之后调用RunWorkerAsync
,但是通过谷歌搜索和堆栈溢出,我知道我无法通过DoWork
更新UI
,我需要在RunWorkerCompleted
中执行此操作
所以我这么做了,但我的问题是我在DoWork
中创建了一个大数据表,这样我就可以通过RunWorkerCompleted
将数据填充到我的网格中,但在完成所有操作后,当它转到RunWorkerCompleted
时,我的应用程序会挂起几秒钟,然后在加载后恢复
我觉得这是因为我正在通过DoWork
获取大量数据,并且当我使用RunWorkerCompleted
显示数据时,它会挂起
我有大约50000个数据,我正在从数据库中获取
如何解决这个问题。除了
BackgroundWorker
之外,我还有什么方法可以使用和做这些事情吗。或者通过BackgroundWorker
只有我可以做一些调整,而且效果很好。您可以从DoWork
方法内部更新UI。您在comments部分所说的错误是因为只有拥有控件的线程才允许修改它。但是,其他线程也可以进行修改,但它们需要将其包装在一个委托中,从而使操作线程安全。在DoWork
方法中,无论何时要更新控件,请执行以下步骤:
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate()
{
// Update the UI here. For example:
// myTextBox.Text = "Hello World!";
});
}
抱歉,我知道这个线程很旧,但我遇到了类似的问题,并找到了一个不需要显式调用
Invoke
的不同解决方案。这是基于这样一个事实,即ProgressChanged
事件(基本上)通过报告某种指示BG工作程序未冻结或卡住的内容来更新UI
确保您的BackgroundWorker
具有.WorkerReportsProgress=true
,并为ProgressChanged
事件添加事件处理程序
现在,神奇的是,当您报告进度时,它会将百分比作为int
(以及类型为object
的可选UserState
参数),但不会检查值是否在任何特定范围内。因此,当我报告从0
到100
的进度百分比时,进度会更新(例如完成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));
...
MyProgressChanged
事件处理程序:
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 ...
}
if(e.ProgressPercentage>=0&&e.ProgressPercentage为什么不能从DoWork
更新UI?@programmer93就是这样。正如我所做的那样,它说的非法跨线程操作:控件“myTextBox”是从创建它的线程以外的线程访问的。
我浏览网页,知道UI更新是不允许的从DoWork
我相信这仍然会阻塞UI线程。如果他将数据添加到较小的块中,可能会不那么明显。不过,我可能只会将记录的数量限制在一个更易于管理的数字。是的,添加较小的数据块是关键。我不知道他使用的数据类型是什么,只是一块块的let’say 100应该可以做到这一点。在任何情况下,它仍然比在工作人员完成时一次向UI提供所有数据要好。@Ginosaji这不应该阻止。Invoke将确保您使用拥有控件窗口句柄的线程。我在backgroundworker Dowork函数中使用它时,它仍然冻结。有什么帮助吗?