【问题标题】:Constantly reporting data to be added to datagridview from background worker hangs the UI不断报告要从后台工作人员添加到 datagridview 的数据会挂起 UI
【发布时间】:2014-04-30 19:28:42
【问题描述】:

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

如果它运行良好且缓慢,那么我的 UI 将被释放到足以让我在出现问题时使用取消按钮,但如果它运行得很快(如果其处理的数据很少),那么 UI 会一直忙于向其中添加行DataGridView 我无法及时使用取消按钮

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

【问题讨论】:

  • DGV 更新必须在 UI 线程上进行,所以我只能建议不要频繁更新 DGV。也许只有每 500 毫秒。
  • 好的,但是如果我添加行并对行进行着色以适应最新情况,我该如何在不更新 ui 的情况下做到这一点?我会更新另一个未显示的 dgv,然后每 500 毫秒将其传递给我有 UI 表单的那个吗?
  • 不,这将是一种迂回的做法。我发布了一个答案来解释我的意思。

标签: c# datagridview backgroundworker


【解决方案1】:

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

【讨论】:

  • 不是我在private void BW_Progress(object sender, ProgressChangedEventArgs e) { datagridview1.rows.add....数据中的每个项目并向 dgv 报告已处理的内容,如果有很多数据,它会很快完成并经常报告 UI 被冻结,因为它不断更新/添加行,所以我无法按下停止或取消
【解决方案2】:

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

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&lt;Result&gt; 被传递,而不是单个 Result,因此您还需要在那里添加一个 for 循环。

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2010-10-25
      • 1970-01-01
      • 1970-01-01
      • 2022-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多