需要解释线程中创建的对象的生存期
本文关键字:对象 生存期 创建 解释 线程 | 更新日期: 2023-09-27 18:31:02
我有一个绑定到 BindingList 的 DevExpress GridControl。
我尝试从线程修改 BindingList,这引发了一个异常,我用谷歌搜索了它并找到了以下解释:
此问题与 XtraGrid 没有直接关系。遗憾的是,您无法在后台线程中更改网格的数据源,因为这会导致很多同步问题。XtraGrid 可能会在后台线程更改基础数据源的同时对它执行一些操作。在这种情况下,网格可能会稍后收到更改通知,并尝试更新数据源中的行,这将导致上述问题。在很多情况下可能会出现此问题。例如,当用户编辑数据、对数据进行分组或 XtraGrid 尝试重新计算汇总时。此问题的唯一解决方案是在后台线程中更改网格的数据源引用(注意:您需要使用 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 组件的几乎所有属性都有该限制。 数据绑定特别麻烦,因为属性分配不直接可见。 仅设置数据源,而不设置绑定设置的所有其他属性。 使用 Control.BeginInvoke 或 Dispatcher.BeginInvoke 可确保在创建控件的同一线程中设置属性值,从而解决线程安全问题。
"一对一"C#垃圾回收
new list
继续存在,通过gcProxies.DataSource
引用。
直到你用完对该列表的引用,你很好。
除非对你访问跨线程或在一个线程中创建并在另一个线程中使用的"列表"有任何特定的"跨线程"问题 - 一切都会很好。
在这里,您只是在初始化,除了通过数据源之外,再也不会使用它,所以一切都很好。
希望这有帮助
编辑:要回答评论,我正在简化一点
您偶然在其上创建对象的线程与对象的"生命周期"无关 - 即线程不拥有该对象。应用程序域可以(这超出了范围),但您可以"跨越"线程边界或执行任何您想要的操作 - 但您"只需要"同步您的代码/对象。