потоковая обработка wpf mvvm.Проблемы с таймером и обратным вызовом

#wpf #mvvm #timer #callback #collectionviewsource

#wpf #mvvm #таймер #обратный вызов #collectionviewsource

Вопрос:

У меня есть приложение WPF, разработанное для платформы MVVM, в котором конструктор ViewModel установил таймер с обратным вызовом.

Обратный вызов времени извлекает ObservableCollection и передает его в поле на виртуальной машине.

У меня есть CollectionViewSource, для свойства Source которого установлено значение ObservableCollection. Я использую CollectionViewSource, потому что хочу включить фильтрацию в коллекции.

Я обнаружил, что когда обратный вызов TimerCallback пытается передать ObservableCollection в локальное поле, свойство Source для CollectionViewSource выдает исключение {«Вызывающий поток не может получить доступ к этому объекту, поскольку он принадлежит другому потоку».}.

Я понимаю исключение, но у меня две проблемы:

  1. Как обойти эту проблему?
  2. И что более важно, почему я получаю эту проблему только при использовании CollectionViewSource? Если я удалю CollectionViewSource и сделаю ObservableCollection общедоступным свойством, я не получу такого исключения.

Любая помощь приветствуется! Спасибо, Драмми

Ответ №1:

  1. Используйте DispatcherTimer вместо класса timer, который вы используете сейчас, и убедитесь, что вы создали его в потоке пользовательского интерфейса.
  2. Вероятно, только с ObservableCollection ваш пользовательский интерфейс не обновляется.

Ответ №2:

Чтобы частично ответить на ваш вопрос, любые обновления ObservableCollection, которые могут быть обнаружены элементами пользовательского интерфейса, должны быть отправлены через поток пользовательского интерфейса. Когда я хочу сделать это в MVVM, моя стратегия заключается в том, чтобы ввести SynchronizationContext в конструктор ViewModel, который я инициализирую во время запуска моего приложения. Это дает мне независимый от View framework способ отправки обновлений, которые должны быть синхронизированы с представлением.

Комментарии:

1. (psst, DispatcherSynchronizationContext)

2. SynchronizationContext.Current извлекает контекст синхронизации для текущего приложения, если доступ к нему осуществляется из потока пользовательского интерфейса; предположительно, это будет DispatcherSynchronizationContext в WPF.