【问题标题】:"BindingSource cannot be its own data source" - error when trying to reset the binding source from a method in another class“BindingSource 不能是它自己的数据源” - 尝试从另一个类中的方法重置绑定源时出错
【发布时间】:2013-01-10 12:57:43
【问题描述】:

我们正在使用BindingSource 绑定DataGridview。所以在主线程中我们给出了这样的。

            class1BindingSource = new BindingSource();
            class1BindingSource.DataSource = class1List;  
            this.dataGridView1.DataSource = class1BindingSource;

之后,我在表单中放置了一个后台工作人员,并在按钮点击中触发。

即在按钮中单击

this.backgroundWorker1.RunWorkerAsync()

BackgroundWorker DoWork Event 我正在尝试更新BindingSource 并尝试更新DataGridview

所以BindingSource 重置是在另一个类的方法中完成的。

DoWork Event

Class2 cl2 = new Class2();
cl2.UpdateBindingSource(class1BindingSource);

UpdateBindingSource Method

public void UpdateBindingSource(BindingSource bs)
        {
            Class1 c1 = bs.Current as Class1;    
            for (int i = 0; i < 1000; i++)
            {
                lock (bs.SyncRoot)
                {
                    c1.MyProperty1 = i;
                    bs.ResetItem(0);
                }
            }
        }

现在我遇到了一个异常,例如 BindingSource 不能是它自己的数据源。不要将DataSourceDataMember 属性设置为引用回BindingSource 的值。

如果我在我的DoWork Event 中执行此操作,那么我可以使用BeginInvoke method 重置控制线程本身中的项目。

但实际上我正在尝试模拟我们的应用场景。所以我想用这种格式解决这个问题。

谁能帮帮我。

【问题讨论】:

    标签: winforms datagridview thread-safety backgroundworker bindingsource


    【解决方案1】:

    问题是您不能在除 gui 线程之外的线程中更新 BindingSource。这是因为BindingSource 将触发一些事件,然后您的数据网格视图将接收这些事件,然后开始自我更新,这将失败,因为它不会在 gui 线程上完成。

    所以在你打电话给RunWorkerAsync()之前你应该打电话给class1BindingSource.SuspendBinding(),在你的RunWorkerCompleted里你应该打电话给class1BindingSource.ResumeBinding()

    还要确保在您的 DoWork 中您不会调用绑定源上的任何方法(就像您对 bs.ResetItem(0) 所做的那样)。

    并删除此锁定语句。它根本没有任何意义(在你的例子中),如果你真的需要它(在你的真实代码中)考虑在你的类中使用一些 private object _Gate = new Object(); 以避免来自外部世界的任何死锁,因为 bs.SyncRoot 是公开可用的.

    【讨论】:

    • 那么我在哪里更新绑定源并在那里重新绑定gridview?
    • 我知道尝试从另一个线程更新数据源时会导致错误,即不是从 UI 线程。有什么方法可以从此方法调用或调用 gridview.BeginInvoke?我想这也可以解决问题..
    • @mahesh:删除lockbs.ResetItem()调用;封装c1.MyProperty1 = i' into a Invoke()` 调用。但这可能会导致其他问题,因为您在两个线程之间稳步跳转。所以最好暂停绑定源,在后台做一些事情,完成后恢复绑定。
    • 对不起,我不明白,我如何将 c1.MyPropert1=i 封装到调用调用中。因为整个事情都在另一个类中。此外,如果我删除 ResetItem(),那么它将如何重新绑定 gridview?
    【解决方案2】:

    我遇到了同样的问题: - 具有 INotifyPropertyChanged 元素的 BindingSource - 更新元素的单独任务。

    建议的解决方案 SuspendBinding 等不起作用。 BindingSource 应该完成类似 IsInvokeRequired 的操作。

    幸运的是,Ivan Stoev 提出了将 BindingSource 子类化并执行与 IsInvokeRequired 类似的事情的绝妙想法。谢谢伊万!

    链接:Update BindingSource from a different Task

    【讨论】:

      【解决方案3】:

      UpdateBindingSource() 不需要太多时间,所以不需要使用backgroundworker。您可以在主线程中调用UpdateBindingSource()。 此外,将 datagridview 操作保留在主线程中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多