我们使用DataGridview
绑定BindingSource
。所以在我们这样给出的主线程中。
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
不能成为自己的数据源。不要将DataSource
和DataMember
属性设置为引用BindingSource
的值。
如果我在DoWork Event
中执行此操作,那么我可以使用BeginInvoke method
重置控件线程中的项目。
但实际上我正在尝试模拟我们的应用场景。所以我想用这种格式解决这个问题。
任何人都可以帮助我。
答案 0 :(得分:14)
问题是你不能在gui线程之外的另一个线程中更新BindingSource
。这是因为BindingSource
将触发一些事件,然后这些事件将由您的数据网格视图接收,然后这些事件将开始自我更新,这将失败,因为它将无法在gui线程上完成。
因此,在致电RunWorkerAsync()
之前,您应致电class1BindingSource.SuspendBinding()
,在RunWorkerCompleted
内,您应致电class1BindingSource.ResumeBinding()
。
同时确保在DoWork
内你不会在绑定源上调用任何方法(就像你对bs.ResetItem(0)
所做的那样)。
并删除此锁定语句。它根本没有任何意义(在你的例子中),如果你真的需要它(在你的实际代码中)考虑在你的类中使用一些private object _Gate = new Object();
来避免来自外部世界的任何死锁,导致{{1} }是公开的。
答案 1 :(得分:2)
我有同样的问题: - 具有INotifyPropertyChanged元素的BindingSource - 更新元素的单独任务。
建议的解决方案SuspendBinding等没有用。 BindingSource应该像IsInvokeRequired那样做。
幸运的是,Ivan Stoev带来了对BindingSource进行子类化的绝妙想法,并做了与IsInvokeRequired类似的事情。谢谢伊万!
答案 2 :(得分:0)
UpdateBindingSource()
不需要花费很多时间,因此无需使用backgroundworker
。您可以在主线程中调用UpdateBindingSource()
。
另外,将datagridview操作保持在主线程中。