Асинхронное добавление в ObservableCollection (или альтернативу)

вот что у меня - список с ItemsSource установлен в ObservableCollection<T> - где T-мой пользовательский класс, представляющий файл, содержащий только 2 DependencyProperties: Filename и ThumbnailPath. - В listbox также есть пользовательский DataTemplate определен, чтобы красиво отображать изображение и имя файла под ним.

целью списка является отображение видеофайлов в текущей папке (выбранной в TreeView) с миниатюрами (сгенерированными асинхронно; не является частью этого проблема.)

поэтому, когда я меняю папку в TreeView, ObservableCollection очищается и заполняется снова, что автоматически отражается в элементах списка.

вот проблема: пользовательский интерфейс перестает отвечать на запросы и обновление занимает до нескольких секунд. Опять же, миниатюры здесь не имеют значения (я попытался отключить их). Я думаю что занимает больше всего времени, это построение 50-100 экземпляров моего пользовательского класса и их визуального представление-оно должно инициализировать объект изображения для каждого из них. Но это только мое предположение - не могли бы вы подтвердить или исключить такую возможность?

Я начинаю думать ObservableCollection не может путь пойти здесь, так как из того, что я читал и немного из того, что я пробовал, нет возможности добавлять элементы асинхронно, по крайней мере, если эти элементы DependencyObjects. Я попытался создать экземпляры класса с помощью BackgroundWorker и добавить их в коллекцию в Обработчик событий ProgressChanged, но он выдает исключение (некоторая проблема с потоком vs dependencyobjects).

есть что-то, что я упускаю? Или мне было бы лучше просто отказаться от ObservableCollection и написать старый добрый асинхронный цикл for, чтобы добавить элементы?

2 ответов


поскольку ObservableCollection привязан к UI, поэтому он генерируется в потоке UI, поэтому любые дальнейшие обновления (удалить/добавить/очистить) должны быть в том же потоке UI. Он не разрешает обновления из другого потока.

однако то, что вы можете сделать, это создать insance вашего класса (или все трудоемкие операции в фоновом потоке), и как только вы закончите, добавьте объект в ObservableCollection, используя Dispatcher из-

App.Current.Dispatcher.BeginInvoke((Action)delegate()
                          {
                              observableCollection.Add(instanceOfYourClass);
                          });

что диспетчер do помещает операцию в связанный с ней поток. Следовательно, элемент всегда добавляется в поток пользовательского интерфейса, но может быть создан в фоновом потоке.

вот несколько ссылок, которые могут вам начать работу - обновление от BW и здесь


с .net 4.5 вы можете использовать EnableCollectionSynchronization

 object lockObj = new object();
        BindingOperations.EnableCollectionSynchronization(yourObservableCollection, lockObj);