2

我有一个绑定到 BindingList 的 DevExpress GridControl。

我试图从一个线程修改 BindingList 并且这引发了一个异常,我用谷歌搜索它并找到以下解释:

此问题与 XtraGrid 没有直接关系。不幸的是,您不能在后台线程中更改网格的数据源,因为这会导致很多同步问题。XtraGrid 可能会在您的后台线程更改它的同时对底层数据源执行一些操作。在这种情况下,网格稍后可能会收到更改通知,并会尝试从数据源更新行,这将导致上述问题。很多情况下可能会出现这个问题。例如,当用户编辑数据、对其进行分组或 XtraGrid 尝试重新计算摘要时。此问题的唯一解决方案是在后台线程中更改 Grid 的 DataSource 引用(注意:您需要使用 Invoke 方法来实现它)。换个说法,在后台线程中,您应该使用 DataSource 的本地副本,并在必要时将其克隆传递给 Grid 的 DataSource。在随附的示例中,您将找到一个演示此方法的示例项目。

我尝试了它所说的,结果是:

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(原始数据源)

4

2 回答 2

3

我认为您的困惑源于您认为 .NET 对象与创建它的线程相关联。情况并非如此,进程中的所有线程共享同一个 GC 堆。在一个线程中创建的 List<> 对象与另一个线程中的 List<> 没有什么不同,它不会以任何方式使创建它的线程保持活动状态。

线程的一个问题是有很多类不是线程安全的。任何 UI 组件肯定都是这种情况。您不能做的是从另一个线程分配此类对象的属性,而该属性值也可以在 UI 线程中使用。UI 组件的几乎所有属性都有这个限制。数据绑定特别麻烦,因为属性分配不是直接可见的。您只设置 DataSource,而不是绑定设置的所有其他属性。使用 Control.BeginInvoke 或 Dispatcher.BeginInvoke 可确保在创建控件的同一线程中设置属性值,从而解决线程安全问题。

于 2012-04-14T17:21:02.937 回答
2

那是“一对一”的 C# 垃圾收集

new list继续存在,通过gcProxies.DataSource.

直到您用完对该列表的引用为止,您都很好。

除非您正在访问跨线程或在一个线程中创建并在另一个线程中使用的“列表”有任何特定的“跨线程”问题 - 一切都会很好。
在这里,您只是在初始化并且除了通过 DataSource 之外再也不会使用它,所以一切都很好。

希望这可以帮助

编辑:回答评论,我简化了一下

您偶然创建对象的线程与对象的“生命周期”无关 - 即线程不拥有该对象。应用程序域可以(超出范围),但您可以“跨越”线程边界或做任何您想做的事情 - 但您“只需要”同步您的代码/对象。

于 2012-04-14T13:38:41.693 回答