交叉线程问题更新数据源

时间:2012-06-15 19:44:59

标签: c# .net multithreading

目标:

一旦我点击用户界面上的开始按钮,我目前就会解雇两名后台工作人员。

BGWorker 1负责调用.dll方法来抓取网站 BGWorker 2负责使用Datasource = source setter

更新DataGridView

的问题:

我的dll收到的参数是对.dll运行时将填充的数据源的引用。所以基本上,.dll会偶尔在数据源中添加一个对象,直到它完成运行。

BGWorker 2执行此操作:

while (1 == 1) // Runs until is it manually disposed
{
    CoursesGrid.BeginInvoke // inline method 
    (
        (Action) delegate 
        {
            if (_coursesSource.Count > 0) // if source is not empty,Binds.
            {
                try
                { 
                    CoursesGrid.DataSource = _coursesSource;
                    CoursesGrid.EndEdit();
                }
                catch (Exception ex)
                {
                    Logs.LogWriter.LogError(ex);
                }                   
            }
            else
            {
                // Signals User To keep Waiting
            }
        }
     );
Thread.Sleep(4000);

行为流程

  • Dll已被调用
  • 方法解析元素并添加到源
  • 最终,BGWorker 2唤醒并将DataGridView源绑定到修改后的源
  • Dll线程继续解析但在尝试向源添加新元素时失败

TL:DR: 线程1写入源 线程2读取此修改后的源,并将其绑定到DataGridView,它将刷新 线程1无法再次在源上写入:

"Cross-thread operation not valid: Control 'CoursesGrid' accessed from a thread other than the thread it was created on."}

两个线程都处理相同的源,但BGWorker 2只将它绑定到接口,这应该可以正常工作。知道这里可能会发生什么吗?

1 个答案:

答案 0 :(得分:2)

我认为发生的事情是您将数据网格绑定到_coursesSource,这会导致数据网格显示第一行。然后,稍后,您正在修改相同的 _coursesSource实例,该实例可能触发属性更改或集合更改通知,这会导致数据网格尝试自行更新(即显示新添加的行) )。

但是由于修改发生在另一个线程上,数据网格“听到”并响应的事件也发生在导致跨线程冲突的后台线程上。

你需要做的是a)将添加到_coursesSource的元素编组到UI线程上(它听起来不像你可以轻易做到的),或b)绑定到{{{ 1}}然后在您的BGWorker 2中,每当您更新_coursesSource将网格重新绑定到新副本时,网格永远不会“听到”更改通知,它始终只是绑定到新的副本集合。这不是最有效的做事方式,但它应该为你完成工作。