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 шт):

Автор решения: Gardes

Прочитав документацию BindingOperations.EnableCollectionSynchronization можно заметить что:

CollectionView поддерживает «теневую копию» коллекции для использования в потоке пользовательского интерфейса.

В итоге вы можете изменить коллекцию в любом потоке, и эти изменения в конечном итоге появятся в ItemsControl, когда поток пользовательского интерфейса успеет «наверстать упущенное». Реализация была настроена таким образом, чтобы регулировать скорость изменения потока в потоке пользовательского интерфейса, чтобы фоновые потоки не перегружали поток пользовательского интерфейса и не позволяли реагировать на обычный пользовательский ввод.

и сделать вывод: что InternalList это и есть та самая "теневая копия" которая отстает от оригинальной коллекции, чтобы не тормозить UI.

→ Ссылка