2013-11-01 3 views
7

Я пытаюсь понять эту концепцию, и даже после многих экспериментов я до сих пор не могу понять, что лучше всего использовать с ObservableCollections в WPF и с использованием BindingOperations.EnableCollectionSynchronization.BindingOperations.EnableCollectionSynchronization mystery in WPF

Если у меня есть ViewModel с наблюдаемой коллекцией и включить сбор синхронизацию на нем, используя блокировку, как показано ниже:

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 должна выполняться через поток пользовательского интерфейса, иначе существует вероятность исключений, возникающих при доступе к коллекции через потоки неинтерфейса. – Ruskin

+0

. Вы обновляете 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 тоже будет работать, в большинстве случаев, IMHO).

+0

Спасибо за это, я думаю, чтобы избежать добавления класса BindingOperations, поэтому мы решили его с помощью этого ... см. Ответ ниже :) – Ruskin

6

Мы, наконец, добрались до нижней части его:

Мы должны включить CollectionSynchronization на диспетчеру:

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

Тогда каждый раз, когда любой другой поток хочет получить доступ к наблюдаемым вы можете просто:

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