【问题标题】:A BackgroundWorker returning null without Exception error when the same operations done outside of it return a value当在其外部完成的相同操作返回值时,BackgroundWorker 返回 null 而没有异常错误
【发布时间】:2022-01-06 15:41:58
【问题描述】:

我有几个 BackgroundWorkersTabPage 中执行相同的任务:他们从 MySql 数据库中提取数据,并在完成后更新 BindingSource 图表

他们中的一个人最近开始行动起来。代码如下:

private void bgwRefreshChartMoisCourant_DoWork(object sender, DoWorkEventArgs e)
{
      trimlineSalesReportDataSet.viewventesparutilisateurmoiscourantDataTable dT = new trimlineSalesReportDataSet.viewventesparutilisateurmoiscourantDataTable();

      this.viewventesparutilisateurmoiscourantTableAdapter.Fill(dT);
      e.Result = dT;
}

private trimlineSalesReportDataSet.viewventesparutilisateurmoiscourantDataTable salesThisMonthDataTable = new trimlineSalesReportDataSet.viewventesparutilisateurmoiscourantDataTable();

private void bgwRefreshChartMoisCourant_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
      salesThisMonthDataTable = new trimlineSalesReportDataSet.viewventesparutilisateurmoiscourantDataTable();
      salesThisMonthDataTable = (trimlineSalesReportDataSet.viewventesparutilisateurmoiscourantDataTable)e.Result;

      this.viewventesparutilisateurmoiscourantBindingSource.DataMember = "";
      this.viewventesparutilisateurmoiscourantBindingSource.DataSource = salesThisMonthDataTable; 
            
      // If the sales are null at the beginning of a month, the filter and sorting will throw an error
      if (e.Result!=null)
      {
          this.viewventesparutilisateurmoiscourantBindingSource.Filter = "Total<>0 AND Vendeur<>'Total'";
          this.viewventesparutilisateurmoiscourantBindingSource.Sort = "Total ASC";
      }

      this.chartSalespersonsThisMonth.DataSource = this.viewventesparutilisateurmoiscourantBindingSource;
      this.chartSalespersonsThisMonth.DataBind();
}

现在很奇怪,因为我无法单步执行 BackgroundWorker_DoWork 事件,如果我将代码复制到 RunWorkerCompleted 如下图,那么我得到的是真实数据,不是null。

private void bgwRefreshChartMoisCourant_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
      // Temporary fix for Background Worker e.Result which is null for some reason, with no Exception error thrown (e.Cancel and e.Error are both null)
      trimlineSalesReportDataSet.viewventesparutilisateurmoiscourantDataTable dT = new trimlineSalesReportDataSet.viewventesparutilisateurmoiscourantDataTable();
      this.viewventesparutilisateurmoiscourantTableAdapter.Fill(dT);

      salesThisMonthDataTable = new trimlineSalesReportDataSet.viewventesparutilisateurmoiscourantDataTable();
      salesThisMonthDataTable = (trimlineSalesReportDataSet.viewventesparutilisateurmoiscourantDataTable)e.Result;

      this.viewventesparutilisateurmoiscourantBindingSource.DataMember = "";
      this.viewventesparutilisateurmoiscourantBindingSource.DataSource = dT;      // Temporary fix
            
      // If the sales are null at the beginning of a month, the filter and sorting will throw an error
      if (e.Result!=null)
      {
          this.viewventesparutilisateurmoiscourantBindingSource.Filter = "Total<>0 AND Vendeur<>'Total'";
          this.viewventesparutilisateurmoiscourantBindingSource.Sort = "Total ASC";
      }

      this.chartSalespersonsThisMonth.DataSource = this.viewventesparutilisateurmoiscourantBindingSource;
      this.chartSalespersonsThisMonth.DataBind();
}

这怎么可能?相同的代码如何在一个线程中返回空值,而在另一个线程中返回一组数据?

我最近在本节中对代码所做的唯一更改是添加了if (e.Result!=null) 部分,因为当月没有数据并且设置了 Sort 属性时,它会抛出异常错误。但是现在有了数据,只是没有看到而已。几个月来一直运行良好。除了这个月是新的一年,其他的都没有改变。起初我认为 MySQL 视图 有缺陷,但不是。

对我为什么或什至如何找出问题所在有什么想法吗?

【问题讨论】:

  • 为什么不能单步执行BackgroundWorker_DoWork?您应该能够在事件处理程序的开始处设置断点。如有必要,您可以在单步执行该代码时冻结调试器中的其他线程。
  • 阿门“冻结其他人” - 我经常认为如果 VS 为不同线程着色前进的黄色条不同颜色会很好,以便在代码跳转时更明显像疯了似的,你正在看不同的线程步进..
  • 我完全支持描述性变量名称,但我想即使我也会减少一点 viewventesparutilisateurmoiscourantBindingSource :) trimlineSalesReportDataSet.viewventesparutilisateurmoiscourantDataTable dT = new trimlineSalesReportDataSet.viewventesparutilisateurmoiscourantDataTable(); 也是 var 的灵感来源!
  • @EricJ。我尝试设置断点,但它只是通过 DoWork 而不会中断,如果我添加 Debugger.Debug()
  • 代码看起来很奇怪;您通常不需要执行所有这些绑定/取消绑定/重新绑定 - 只需将您的东西绑定到绑定源(绑定到表)它们绑定到并填充基础表..

标签: c# multithreading null backgroundworker


【解决方案1】:

在问题下的 cmets 中对此进行了诊断,结果发现 DoWork 事件处理程序代码已与 DoWork 事件解除绑定。在与设计师合作时,我不时会因各种控件而发生这种情况..

引用计数的代码镜头也可以提示:

顺便说一句,我想说你的代码可能会折叠成这样:

private void bgwRefreshChartMoisCourant_DoWork(object sender, DoWorkEventArgs e)
{
      e.Result = this.VenParMoisCourTableAdapter.GetData();
}

private void bgwRefreshChartMoisCourant_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
      this.VenParMoisCourBindingSource.DataSource = e.Result;
      
      this.VenParMoisCourBindingSource.Filter = "Total<>0 AND Vendeur<>'Total'";
      this.VenParMoisCourBindingSource.Sort = "Total ASC";
}

GetData 应该总是返回一个数据表,即使它是空的,所以你可以跳过空检查

另外,也许您已经知道,但您始终可以在数据集中右键单击您的 TableAdapter 并添加更多执行其他过滤的查询,以便查询

SELECT * FROM VenParMoisCour WHERE Total<>0 AND Vendeur<>'Total' ORDER BY Total

首先会保存正在下载的那些记录。询问时为查询起一个好听的名称,例如 FillAllExceptZeroTotal / GetDataByAllExceptZeroTotal,您可以

private void bgwRefreshChartMoisCourant_DoWork(object sender, DoWorkEventArgs e)
{
      e.Result = this.VenParMoisCourTableAdapter.GetDataByAllExceptZeroTotal();
}

private void bgwRefreshChartMoisCourant_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
      this.VenParMoisCourBindingSource.DataSource = e.Result;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-11
    • 2012-04-14
    • 1970-01-01
    • 1970-01-01
    • 2018-10-18
    • 2016-04-13
    相关资源
    最近更新 更多