BindingOperations.EnableCollectionSynchronization проблемы синхронизацией
Имеется ObservableCollection привязанная к PageCollectionView* созданный на основе ListCollectionView.
public VM()
{
_customs = new ObservableCollection<CustomVM>();
PageCollectionView = new PageCollectionView(_customs, 100);
}
*класс делит внутренний список на страницы. логики затрагивающее асинхронное чтение/запись и т.д. не добавлено.
Коллекция заполнялась в фоновом потоке при помощи:
Application.Current.Dispatcher.InvokeAsync(() => { /*добавление элемента в коллекцию */ });
Все работает отлично, пока коллекция не начинает активно заполнятся, в следствие чего UI - поток блокируется до тех пор пока коллекция не перестанет заполнятся.
Выходом из ситуации было использовать BindingOperations.EnableCollectionSynchronization и добавлять элементы без Dispatcher.InvokeAsync:
private object lockObj = new object();
public VM()
{
_customs = new ObservableCollection<CustomVM>();
BindingOperations.EnableCollectionSynchronization(_customs, lockObj);
PageCollectionView = new PageCollectionView(_customs, 100);
}
UI - поток перестал блокироваться при активном заполнении коллекции, НО я заметил что ListCollectionView.InternalList возвращает каждый раз разное количество элементов, в следствие чего не правильно рассчитываются некоторые свойства в PageCollectionView.
Нашел похожую проблему, но решение там свелось к использованию как Dispatcher.InvokeAsync.
Как с этим бороться, чтобы ListCollectionView.InternalList при обращении возвращало все элементы?.
Ответы (1 шт):
Прочитав документацию BindingOperations.EnableCollectionSynchronization можно заметить что:
CollectionView поддерживает «теневую копию» коллекции для использования в потоке пользовательского интерфейса.
В итоге вы можете изменить коллекцию в любом потоке, и эти изменения в конечном итоге появятся в ItemsControl, когда поток пользовательского интерфейса успеет «наверстать упущенное». Реализация была настроена таким образом, чтобы регулировать скорость изменения потока в потоке пользовательского интерфейса, чтобы фоновые потоки не перегружали поток пользовательского интерфейса и не позволяли реагировать на обычный пользовательский ввод.
и сделать вывод: что InternalList это и есть та самая "теневая копия" которая отстает от оригинальной коллекции, чтобы не тормозить UI.