2013-11-01 174 views
7

我一直在努力去理解这个概念,即使经过很多实验,我仍然无法弄清楚WP7中的ObservableCollections和使用BindingOperations.EnableCollectionSynchronization的最佳实践。BindingOperations.EnableCollectionSynchronization在WPF中的神秘

如果我有一个观察的集合视图模型和我能够使用锁它集同步如下图所示:

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

这是否意味着,每次修改,并列举了可观察的集合将:

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

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

这催生这一切,即使使用BindingOperations.EnableCollectionSynchronization并使用我传递到了方法相同锁锁定的项目后,非常偶然,我得到了“这种类型的CollectionView的不支持从改变其SourceCollection问题与分派器线程不同的线程“。例外

+0

你可以发布代码,你如何试图修改集合和从哪里?我尝试了它在小应用程序,它完美的作品。 –

+0

问题是间歇性的,所以无法添加代码来重现它。问题是BindingOperations.EnableSynchronization必须通过UI线程完成,否则当通过非UI线程访问集合时可能会引发异常 – Ruskin

+0

您是在主UI线程还是从后台线程更新ObservableCollection ?如果来自bg线程,您是否正在使用对'Application.Current.Dispatcher.BeginInvoke()'的调用进行更新?你有没有尝试过使用简单的'lock()'语句(〜理智)来调用......? – code4life

回答

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也可以工作,大部分时间,恕我直言)。

+0

谢谢你,我想避免他们添加BindingOperations类,所以我们使用它来解决它...查看下面的答案:) – Ruskin

6

我们终于到它的底部:

我们必须对调度员能CollectionSynchronization:

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

然后每次任何其他线程想要访问观察到的,你可以简单地说:

lock (m_observableCollectionLock) 
    m_observableCollection.Add(...)