【问题标题】:BackgroundWorker not firing RunWorkerCompletedBackgroundWorker 没有触发 RunWorkerCompleted
【发布时间】:2011-11-29 21:48:41
【问题描述】:

我第一次运行我的 backgroundworker 时它运行正确 - 在后台更新数据表,然后 RunWorkerCompleted 将数据表设置为 datagridview 数据源。

如果我再次运行它,datagridview 会清除并且不会更新。我不知道为什么。

当我的代码命中 dgvReadWrites.DataSource 时,我已验证数据表包含行。

    private void btnGenerateStats_Click(object sender, EventArgs e)
    {
        dtJobReadWrite.Columns.Clear();
        dtJobReadWrite.Rows.Clear();
        dgvReadWrites.DataSource = dtJobReadWrite;

        List<Tuple<string, string>>jobs = new List<Tuple<string, string>>();

        foreach (ListViewItem job in lstJobs.SelectedItems)
        {
            jobs.Add(new Tuple<string, string>(job.Text, job.SubItems[2].Text));
        }
        BackgroundWorker bgw = new BackgroundWorker();
        bgw.WorkerReportsProgress = true;
        bgw.WorkerSupportsCancellation = true;
        bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
        bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
        pbarGenStats.Style = ProgressBarStyle.Marquee;
        pbarGenStats.MarqueeAnimationSpeed = 30;
        pbarGenStats.Visible = true;
        bgw.RunWorkerAsync(jobs);
    }


    private void bgw_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker bgw = sender as BackgroundWorker;
        List<Tuple<string, string>> jobs = (List<Tuple<string, string>>)e.Argument;
        GetReadWriteStats(jobs);
    }

    private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        BackgroundWorker bgw = sender as BackgroundWorker;
        bgw.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
        bgw.DoWork -= new DoWorkEventHandler(bgw_DoWork);
        pbarGenStats.MarqueeAnimationSpeed = 0;
        pbarGenStats.Value = 0;
        pbarGenStats.Visible = false;
        dgvReadWrites.DataSource = dtJobReadWrite;
        dgvReadWrites.Visible = true;
        dgvReadWrites.Refresh();
    } 

【问题讨论】:

  • 您为什么要明确取消订阅 RunWorkerCompleted 上的事件?
  • 放弃这个线程的建议:stackoverflow.com/questions/2542326/… 似乎有类似的问题。但是,删除这些行并不能解决问题。
  • 您可以尝试使本地后台工作人员变量并且只需订阅一次事件。然后你不需要在完整的方法中删除处理程序
  • “datagridview 清除且不更新”。这是否意味着没有调用 bgw_RunWorkerCompleted ?你在调试器中测试过这个吗?取消订阅事件没问题,问题出在其他地方。
  • @Alex - 是的,你是对的:第二次,它结束了“DoWork”并且没有进入 RunWorkerCompleted。

标签: c# datagridview backgroundworker


【解决方案1】:
private void btnGenerateStats_Click(object sender, EventArgs e)
{
    //...
    dgvReadWrites.DataSource = dtJobReadWrite;
    // etc...
}

这是一个问题,您正在 BGW 中更新 dtJobReadWrite。这会导致绑定的网格被工作线程更新。非法的,控件不是线程安全的,只能从创建它们的线程更新。这通常会被检查,在调试时会产生 InvalidOperationException,但此检查不适用于绑定控件。

接下来出错的地方到处都是,你很幸运,你遇到了一个高度可重复的死锁。更常见的不当行为是偶尔的绘画伪影和仅在您不关闭时出现的僵局。修复:

    dgvReadWrites.DataSource = null;

并在 RunWorkerCompleted 事件处理程序中重新绑定网格,就像您已经做的那样。

【讨论】:

    【解决方案2】:

    因为您取消订阅这些活动

    bgw.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
    bgw.DoWork -= new DoWorkEventHandler(bgw_DoWork);
    

    删除那些行

    【讨论】:

      【解决方案3】:

      为什么每次要运行时都创建一个新的 BackgroundWorker?如果您使用 BackgroundWorker 的一个实例(GetReadWriteWorker 或类似的东西),只订阅一次事件,然后在 btnGenerateStats_Click 上运行该工作程序 Async,我想看看这段代码会发生什么。

      【讨论】:

      • 重用组件只会保留更多状态。并且 OP 已经存在可重复性问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-31
      • 1970-01-01
      • 2011-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多