Winforms &引用;BindingSource不能是自己的数据源";-尝试从另一个类中的方法重置绑定源时出错
我们正在使用Winforms &引用;BindingSource不能是自己的数据源";-尝试从另一个类中的方法重置绑定源时出错,winforms,datagridview,thread-safety,backgroundworker,bindingsource,Winforms,Datagridview,Thread Safety,Backgroundworker,Bindingsource,我们正在使用BindingSource绑定一个DataGridview。所以在主线程中,我们给出了如下内容 class1BindingSource = new BindingSource(); class1BindingSource.DataSource = class1List; this.dataGridView1.DataSource = class1BindingSource; 之后,我在表单中放置了一个后台工
BindingSource
绑定一个DataGridview
。所以在主线程中,我们给出了如下内容
class1BindingSource = new BindingSource();
class1BindingSource.DataSource = class1List;
this.dataGridView1.DataSource = class1BindingSource;
之后,我在表单中放置了一个后台工作程序,并通过单击按钮触发
i、 e.在按钮中单击
this.backgroundWorker1.RunWorkerAsync()
在BackgroundWorker
DoWork事件中
我试图更新BindingSource
,并尝试更新DataGridview
因此,BindingSource
reset是在另一个类的方法中完成的
DoWork事件
UpdateBindingSource方法
public void UpdateBindingSource(BindingSource-bs)
{
Class1 c1=bs。电流为Class1;
对于(int i=0;i<1000;i++)
{
锁(bs.SyncRoot)
{
c1.MyProperty1=i;
b.第(0)项;
}
}
}
现在我得到了一个异常,比如BindingSource
不能是它自己的数据源。不要将DataSource
和DataMember
属性设置为引用BindingSource
的值
如果我在我的DoWork事件中执行此操作
,那么我可以使用BeginInvoke方法
重置控制线程本身中的项
但实际上,我正在尝试模拟我们的应用程序场景。所以我想用这种形式来解决这个问题
有人能帮我吗。问题是除了gui线程之外,您不能在其他线程中更新
BindingSource
。这是因为,BindingSource
将触发一些事件,然后数据网格视图将接收这些事件,然后数据网格视图将开始自我更新,这将失败,因为它不会在gui线程上执行
因此,在调用RunWorkerAsync()
之前,应该调用classbindingsource.SuspendBinding()
,并在RunWorkerCompleted
中调用classbindingsource.ResumeBinding()
还要确保在DoWork
中不会调用绑定源上的任何方法(就像您对bs.ResetItem(0)
所做的那样)
并删除此lock语句。它只是没有任何意义(在你的例子中),如果你真的需要它(在你的真实代码中)考虑使用一些<代码>私有对象,{门=新对象();code>在您的类中,为了避免来自外部世界的任何死锁,因为bs.SyncRoot
是公开可用的。我遇到了相同的问题:
-具有INotifyPropertyChanged元素的BindingSource
-更新元素的单独任务
建议的解决方案SuspendBinding等不起作用。BindingSource应该执行类似IsInvokeRequired的操作
幸运的是,Ivan Stoev想出了一个绝妙的主意,将BindingSource子类化,并按照IsInvoke的要求做一些类似的事情。谢谢你,伊万
链接:UpdateBindingSource()
不需要花费太多时间,因此无需使用backgroundworker
。您可以在主线程中调用UpdateBindingSource()
。
另外,将datagridview操作保留在主线程中。因此,我在哪里更新绑定源,在哪里通过重新绑定gridview?我知道在尝试从另一个线程(即不是从UI线程)更新数据源时会导致错误。是否有任何方法可以从此方法调用或调用gridview.BeginInvoke?我想这也可以解决问题。@mahesh:移除
锁
和bs.ResetItem()
调用;将c1.MyProperty1=i'封装到一个Invoke()`调用中。但这可能会导致其他问题,因为您正在两个线程之间稳步跳跃。因此,最好挂起绑定源,在后台执行这些操作,并在绑定完成后恢复绑定。抱歉,我不明白,如何将c1.MyPropert1=i封装到调用中。因为整个过程都在另一个类中。另外,如果我删除ResetItem(),那么它将如何重新绑定gridview?
Class2 cl2 = new Class2();
cl2.UpdateBindingSource(class1BindingSource);
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);
}
}
}