13

我一直在努力掌握这个概念,即使经过多次实验,我仍然无法弄清楚 WPF 中的 ObservableCollections 和使用 BindingOperations.EnableCollectionSynchronization 的最佳实践是什么。

如果我有一个带有可观察集合的视图模型,并且我使用锁在其上启用集合同步,如下所示:

m_obsverableCollection = new ObservableCollection<..>;
BindingOperations.EnableCollectionSynchronization(m_obsverableCollection,
                                                   m_obsverableCollectionLock);

这是否意味着对该可观察集合的每次修改和枚举都将:

  1. 使用 m_obsverableCollectionLock 自动锁定集合?
  2. Marshall 在创建集合的线程上进行所有修改?
  3. Marshall 对调用绑定操作的线程进行所有修改?

使用 BindingOperations.EnableCollectionSynchronization 时,我是否需要明确地进行任何类型的锁定?

产生这一切的问题是,即使在使用 BindingOperations.EnableCollectionSynchronization 并使用我传递给该方法的同一锁锁定项目之后,我偶尔也会收到“这种类型的 CollectionView 不支持从不同于调度线程。” 例外

4

2 回答 2

13

我们终于找到了它的底部:

我们必须在调度程序上启用 CollectionSynchronization:

Application.Current.Dispatcher.BeginInvoke(new Action(()=>
{
    BindingOperations.EnableCollectionSynchronization(m_obsverableCollection, m_observableCollectionLock);
}));

然后每次任何其他线程想要访问可观察对象时,您都可以简单地:

lock (m_observableCollectionLock)
    m_observableCollection.Add(...)
于 2014-12-15T07:52:16.040 回答
2

我没有使用那种特定的语法,但是每当我需要ObservableCollection从后台线程更新一个时,我都会遵循这个模式:

// i just typed this off the top of my head, so be forewarned...  :)
lock(someLockingObj)
{
    Application.Current.Dispatcher.BeginInvoke(new Action(()=>
    {
       ... update here....
    }));
}

通常,您遇到的错误发生在 bg 线程尝试ObservableCollection直接更新时,没有Dispatcher.BeginInvoke(或者甚至Invoke在大多数情况下也可以工作,恕我直言)。

于 2014-12-04T04:36:54.507 回答