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

本文关键字:datagridview 数据 UI 挂起 添加 报告 工作者 后台 | 更新日期: 2023-09-27 18:00:55

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

如果它运行良好且缓慢,那么如果出现问题,我的UI就足够空闲,可以使用取消按钮,但如果它运行得很快(如果它处理的数据很少(,那么UI就一直忙于向DataGridView添加行,我就无法及时使用取消按钮

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

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

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

在后台工作者的运行方法中,我假设您有这样的东西:

foreach (var result in database.GetAllResults()) {
    bw.ReportProgress(result);
}

您可以尝试将代码限制为每500毫秒更新一次(或者任何看起来最有效的数字(,方法是将其更改为以下内容:

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);

当然,在进度处理程序中,现在传递的是一个List<Result>,而不是单个Result,因此还需要在那里添加一个for循环。

根据MSDN,Thread.Sleep(0(在每个ReportProgress之后都应该这样做:

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