【问题标题】:How can I bind to data being populated in another thread?如何绑定到另一个线程中填充的数据?
【发布时间】:2015-09-14 13:26:59
【问题描述】:

我有一个后台工作人员用MyClass 填写System.Collections.Concurrent.ConcurrentQueue。然后我有一个System.ComponentModel.BackgroundWorkerConcurrentQueue 清空为System.Data.DataTable。我已将该表公开,以便我可以绑定到它以更新 WinForms 图表。但是,我开始意识到 DataTable 不是线程安全的。

我可以用什么代替?我喜欢DataTable,因为我可以简单地通过向 MyClass 添加属性来添加列,并且很容易绑定到我的图表。我缺少这个问题的标准解决方案吗?

编辑: 我将绘制大量数据(成千上万的点),这就是为什么我想使用绑定 - 以提高性能。

Form_main.cs:

public Form_main()
{
    InitializeComponent();
    // ... add some series data
    chart_highLevel.DataSource = MyClass.dt; // this being populated in a BackgroundWorker in MyClass
}

private void timer_updateGui_Tick(object sender, EventArgs e)
{
    chart_highLevel.DataBind(); // Update the databind
}

MyClass.cs

public DataTable dt = {get; private set;}
private void bw_analyser_DoWork(object sender, DoWorkEventArgs e)
{
    while(true)
    {    
        // ... populate 'values'
        dt.Rows.Add(values); // values are the data to fill the DataTable, dt
    }
}

【问题讨论】:

  • 那么你是有多个线程访问数据表还是你在谈论跨线程异常??
  • 我有一个线程(BackgroundWorker)填充数据表。然后 UI 线程每秒从 Windows.Forms.Timer 调用一次 Chart.DataBind()。这会导致错误,因为“集合已修改”
  • 你能发布你的代码吗?我认为你必须使用锁来实现线程同步。
  • 我已经发布了一段精简且可读的代码,它应该展示结构......
  • @zotty 为什么需要后台工作者?使用计时器是不够的,然后在每个滴答中加载额外的数据并将它们添加到数据表中,然后再次将其绑定到图表?

标签: c# .net multithreading winforms datatable


【解决方案1】:

您必须使用 lock 语句来同步访问同一对象的线程,即您的情况下的数据表。此外,Data Table 具有克隆功能,可用于在分配给数据源之前创建新的数据表。这样,DataBind 操作将使用永远不会被后台线程修改的数据表。因此集合被修改的问题将得到解决。 尝试以下更改

 private void timer_updateGui_Tick(object sender, EventArgs e)
{
    lock(MyClass.dt)
    {
    chart_highLevel.DataSource = MyClass.dt.Copy();
    }
    chart_highLevel.DataBind(); // Update the databind

}
    public DataTable dt = {get; private set;}
private void bw_analyser_DoWork(object sender, DoWorkEventArgs e)
{
    while(true)
    {    
        // ... populate 'values'
        lock(dt)
        {
        dt.Rows.Add(values); // values are the data to fill the DataTable, dt          }
    }
}

【讨论】:

  • 先加锁再克隆比先加锁再绑定有优势吗?
  • @zotty 是的,克隆将确保创建数据表的副本并将其用于绑定目的....原始数据表可以在单独的线程上修改而不会影响绑定过程....一个在 lock 语句本身中进行绑定的缺点是它会持有更长时间的锁,直到完整的绑定过程完成......并且背景线程必须等待数据表直到锁定被释放......所以上述方法改进了性能太...
  • 只是为了让您知道上面的 .Clone() 应该是 .Copy()。 Clone 只是克隆了 DataTable 的结构,Copy 也带来了数据。除此之外,很好的答案,谢谢!
  • @zotty 感谢您让我知道......并更新了相同的答案......
猜你喜欢
  • 2021-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-12
  • 1970-01-01
  • 2020-11-28
  • 1970-01-01
相关资源
最近更新 更多