c# - 如何通过工作线程更新 ObservableCollection?

标签 c# wpf multithreading observablecollection

我有一个 ObservableCollection<A> a_collection;该集合包含“n”项。每个项目 A 看起来像这样:

public class A : INotifyPropertyChanged
{

    public ObservableCollection<B> b_subcollection;
    Thread m_worker;
}

基本上,它都连接到一个 WPF ListView + 一个显示 b_subcollection 的详细信息 View 控件。在单独的 ListView 中选择的项目(2 向绑定(bind)、属性更新等)。

当我开始实现线程时,问题出现了。整个想法是让整个 a_collection使用它的工作线程来“工作”,然后更新它们各自的 b_subcollections并让 gui 实时显示结果。

当我尝试时,我得到一个异常,说只有 Dispatcher 线程可以修改 ObservableCollection,然后工作就停止了。

谁能解释这个问题,以及如何解决这个问题?

最佳答案

.NET 4.5 的新选项

从 .NET 4.5 开始,有一个内置机制可以自动同步对集合的访问并将 CollectionChanged 事件分派(dispatch)到 UI 线程。要启用此功能,您需要调用 BindingOperations.EnableCollectionSynchronization 从您的 UI 线程中

EnableCollectionSynchronization 做了两件事:

  1. 记住调用它的线程,并使数据绑定(bind)管道在该线程上编码 CollectionChanged 事件。
  2. 在处理完编码事件之前获取集合的锁,这样运行 UI 线程的事件处理程序就不会在后台线程修改集合时尝试读取集合。

非常重要的是,这并不能解决所有问题:要确保线程安全地访问本质上不是线程安全的集合,您必须与框架合作当集合即将被修改时,从后台线程获取相同的锁。

因此正确操作所需的步骤是:

1。确定您将使用哪种锁定方式

这将决定必须使用 EnableCollectionSynchronization 的哪个重载。大多数情况下,一个简单的 lock 语句就足够了 this overload是标准选择,但如果您使用一些奇特的同步机制,还有 support for custom locks .

2。创建集合并启用同步

根据所选的锁定机制,在 UI 线程上调用适当的重载。如果使用标准的 lock 语句,您需要提供锁定对象作为参数。如果使用自定义同步,您需要提供 CollectionSynchronizationCallback委托(delegate)和上下文对象(可以是 null)。调用时,此委托(delegate)必须获取您的自定义锁,调用传递给它的 Action 并在返回前释放锁。

3。通过在修改之前锁定集合来配合

当您要自己修改集合时,您还必须使用相同的机制锁定该集合;在简单场景中使用传递给 EnableCollectionSynchronization 的相同锁定对象上的 lock() 执行此操作,或者在自定义场景中使用相同的自定义同步机制。

关于c# - 如何通过工作线程更新 ObservableCollection?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2091988/

相关文章:

c# - 软件设计只有接口(interface)?

c# - 没有 IEnumerable 但有 IEnumerator 的生活

wpf - 我应该使用哪些 WPF 框架?

c# - 当所有后台线程池线程完成时得到通知

java - 线程中的方法调用给出 "Can' t 在线程内创建处理程序“异常

c# - 独立存储不支持给定路径的格式

c# - 从 JObject 中提取值

c# - 如何将 RibbonGroup 向右对齐?

c# - WPF 控件在窗口中的位置?

java - 使用同步获取意外值