0

目标:

单击用户界面上的开始按钮后,我目前会解雇两个后台工作人员。

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 源绑定到修改后的 Source
  • 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 只将它绑定到接口,这应该可以工作。知道这里可能会发生什么吗?

4

1 回答 1

2

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

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

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

于 2012-06-15T20:01:49.980 回答