C# 不断报告要从后台工作者添加到datagridview的数据会挂起UI

C# 不断报告要从后台工作者添加到datagridview的数据会挂起UI,c#,datagridview,backgroundworker,C#,Datagridview,Backgroundworker,我有一个从外部源检索数据的BackgroundWorker。 然后,我的BackgroundWorker处理数据并用修改后的数据更新原始源。 我从BackgroundWorker那里返回报告,填写已处理内容的DataGridView等 如果它运行良好且速度缓慢,则我的UI会释放足够的空间,以便在出现问题时使用“取消”按钮,但如果它运行迅速,且数据处理量很小,则UI会一直忙于向DataGridView添加行,而我无法及时使用“取消”按钮 所以。。。我的问题是,什么才是正确的方法来不断更新DataG

我有一个从外部源检索数据的BackgroundWorker。 然后,我的BackgroundWorker处理数据并用修改后的数据更新原始源。 我从BackgroundWorker那里返回报告,填写已处理内容的DataGridView等

如果它运行良好且速度缓慢,则我的UI会释放足够的空间,以便在出现问题时使用“取消”按钮,但如果它运行迅速,且数据处理量很小,则UI会一直忙于向DataGridView添加行,而我无法及时使用“取消”按钮


所以。。。我的问题是,什么才是正确的方法来不断更新DataGridView,同时仍保留一些UI控件来按cancel,但不会进一步减慢进程。

当BackgroundWorker的RunWorkerCompleted事件触发时,听起来您好像在最后进行所有网格更新。相反,请将BackgroundWorker的WorkerReportsProgress属性设置为true,并让您的DoWork方法调用ReportProgress,只要您想在网格中传递一些新数据。

在BackgroundWorker的run方法中,我假设您有如下内容:

foreach (var result in database.GetAllResults()) {
    bw.ReportProgress(result);
}
var buffer = new List<Result>();
var lastUpdate = DateTime.Now;
foreach (var result in database.GetAllResults()) {
    buffer.Add(result);
    if (DateTime.Now > lastUpdate.AddMilliseconds(500)) {
        bw.ReportProgress(buffer);
        buffer.Clear();
        lastUpdate = DateTime.Now;
    }
}
if (buffer.Any()) bw.ReportProgress(buffer);
您可以尝试将代码限制为每500毫秒更新一次,或者将其更改为以下内容:

foreach (var result in database.GetAllResults()) {
    bw.ReportProgress(result);
}
var buffer = new List<Result>();
var lastUpdate = DateTime.Now;
foreach (var result in database.GetAllResults()) {
    buffer.Add(result);
    if (DateTime.Now > lastUpdate.AddMilliseconds(500)) {
        bw.ReportProgress(buffer);
        buffer.Clear();
        lastUpdate = DateTime.Now;
    }
}
if (buffer.Any()) bw.ReportProgress(buffer);
当然,在您的进度处理程序中,现在传递的是一个列表,而不是一个结果,因此您也需要在其中添加一个for循环。

根据MSDN,在每次报告之后,进度应该这样做:

指定零0以指示应挂起此线程以允许其他等待的线程执行


DGV更新必须在UI线程上进行,因此我建议不要经常更新DGV。可能每500毫秒一次。好的,但是如果我添加行并为行着色以适应正在进行的操作,在没有ui更新的情况下,我怎么做呢?我是否会更新另一个未显示的dgv,然后每隔500毫秒将其传递给我有UI表单的dgv?不,这将是一种循环方式。我发布了一个答案来解释我的意思。不,我在私有void BW_Progressobject sender,progresschangedventargs e{datagridview1.rows.add…}中添加了每一行。问题是后台工作分批下载数据,处理数据中的每一项,并向dgv报告已处理的内容,如果有大量数据,它会非常快速地进行操作,并经常报告,因此UI在不断更新/添加行时会被冻结,因此我无法按“停止”或“取消”