如何从后台线程正确更新数据绑定 datagridview [英] How do you correctly update a databound datagridview from a background thread
问题描述
我有一个实现 INotifyPropertyChanged 的自定义对象.我有这些对象的集合,其中集合基于 BindingList我已经为集合创建了绑定源,并设置了绑定源和数据网格视图的数据源.
I have a custom object that implements INotifyPropertyChanged. I have a collection of these objects where the collection is based on BindingList I have created a binding source for the collection, and set the datasources of the bindingsource and datagridview.
一切都很好,除了我需要从后台线程更新自定义对象的属性.当我这样做时,我收到以下错误:
Everything works great, except I need to update properties on the custom object from background threads. when I do so, I get the following error :
BindingSource 不能是它自己的数据源.不要将 DataSource 和 DataMember 属性设置为引用回 BindingSource 的值
BindingSource cannot be its own data source. Do not set the DataSource and DataMember properties to values that refere back to BindingSource
我发现以下帖子似乎有我的确切问题(和解决方案?),但我无法弄清楚.
I found the following post that seems to have my exact problem (and solution?) but I cannot quite figure it out.
我根据业务对象中的帖子创建并初始化了 oper 变量,然后将两个事件函数放入我的集合类中.这编译正确,但运行时无一例外挂起.
I created and initialized the oper variables per the post in my business object, and then I put the two event functions into my collection class. This compiled correctly, but hangs without exception when run.
我看到很多帖子都说要使用 Invoke/Begin Invoke,但我没有在 UI 上调用任何函数,只是更新业务对象,所以我不确定将调用调用放在哪里.
I have seen many posts saying to use Invoke/Begin Invoke, but I am not calling any functions on the UI, just updating business objects, so I am not sure where I would put the invoke calls.
一个限制:我希望业务对象不知道谁在显示它(因为有多个消费者)所以将 GUI 引用发送到业务对象中,以便我以后能够使用这些引用调用 invoke选项.
One restriction : I want the business object to remain unaware of who is displaying it (as there are multiple consumers) so sending in GUI references into the business object so that I am later able to call invoke using those references is not an option.
推荐答案
我在一个有效的论坛中找到了这个课程.只需使用它而不是 BindingList
I found this class in a forum that works. Just use this instead of BindingList
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Threading;
namespace Utility
{
public class ThreadedBindingList<T> : BindingList<T>
{
SynchronizationContext ctx = SynchronizationContext.Current;
protected override void OnAddingNew(AddingNewEventArgs e)
{
if (ctx == null)
{
BaseAddingNew(e);
}
else
{
ctx.Send(delegate
{
BaseAddingNew(e);
}, null);
}
}
void BaseAddingNew(AddingNewEventArgs e)
{
base.OnAddingNew(e);
}
protected override void OnListChanged(ListChangedEventArgs e)
{
// SynchronizationContext ctx = SynchronizationContext.Current;
if (ctx == null)
{
BaseListChanged(e);
}
else
{
ctx.Send(delegate
{
BaseListChanged(e);
}, null);
}
}
void BaseListChanged(ListChangedEventArgs e)
{
base.OnListChanged(e);
}
}
}
这篇关于如何从后台线程正确更新数据绑定 datagridview的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!