我有一个绑定(bind)到 BindingList 的 DevExpress GridControl。
我尝试从线程修改 BindingList,这引发了异常,我用 google 搜索并找到了以下解释:
此问题与 XtraGrid 没有直接关系。不幸的是,您无法在后台线程中更改网格的数据源,因为这会导致很多同步问题。当您的后台线程更改它时,XtraGrid 可能会同时对底层数据源执行一些操作。在这种情况下,网格稍后可能会收到更改通知,并尝试更新数据源中的行,这将导致上述问题。这个问题在很多情况下都可能出现。例如,当用户编辑数据、对其进行分组或 XtraGrid 尝试重新计算摘要时。此问题的唯一解决方案是在后台线程中更改 Grid 的 DataSource 引用(注意:您需要使用 Invoke 方法来实现它)。换句话说,在后台线程中,您应该使用数据源的本地副本,并在必要时将其克隆传递给网格的数据源。在随附的示例中,您将找到一个演示此方法的示例项目。
我尝试了它所说的,结果是这样的:
proxyWorker = new Thread(() =>
{
//Clone the datasource into the thread
BindingList<Proxy> newList = new BindingList<Proxy>(proxies);
//Set the proxy source to the cloned datasource in the thread
gcProxies.BeginInvoke(new MethodInvoker(delegate { gcProxies.DataSource = newList; }));
//Logic here
});
proxyWorker.Name = "proxyTester";
proxyWorker.Start();
它有效,但我不明白线程结束后数据源会发生什么? newList
不是被销毁了吗?
我的想法是,最后我会重新克隆 newList 并将其设置回 proxies
(原始数据源)
最佳答案
我认为您的困惑源于这样一个事实:您认为 .NET 对象与创建它的线程相关联。事实并非如此,进程中的所有线程共享同一个GC堆。在一个线程中创建的 List<> 对象与另一个线程中创建的 List<> 对象没有什么不同,它不会以任何方式使创建它的线程保持事件状态。
线程的一个问题是,有很多类不是线程安全的。对于任何 UI 组件来说都是如此。您不能做的是从另一个线程分配此类对象的属性,而该属性值也可能在 UI 线程中使用。几乎 UI 组件的所有属性都有该限制。数据绑定(bind)特别麻烦,因为属性分配不直接可见。您仅设置数据源,而不是绑定(bind)设置的所有其他属性。使用Control.BeginInvoke或Dispatcher.BeginInvoke可以确保在创建控件的同一线程中设置属性值,从而解决线程安全问题。
关于c# - 需要对线程中创建的对象的生命周期进行解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10154033/