Массовые обновления сложного интерфейса

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

Теперь контекст данных этих небольших, но сложных областей имеет одинаково сложные модели представления, такие как StatusBarVM, ChartingVM, GeoMapVM и т. Д. Они реализуют INotifyPropertyChanged и ObservableCollections.

Подсчитывая мои обновления, я вижу, что у меня есть около 5000 элементов пользовательского интерфейса (метки, индикаторы выполнения, точки данных диаграммы, bgcolorsbrushes и т. Д.), Которые меняются со скоростью 1000 обновлений элементов данных в секунду.

Каков наилучший способ добиться массового обновления данных в пользовательском интерфейсе WPF?

Способна ли модель связывания WPF для такого рода огромных обновлений? Если так, как? Потому что я вижу, что это не оптимально в моем случае. Я также использую bgworker (для индикаторов прогресса) и использую DIspatcher BeginInvoke... но дело в том, что даже тогда обновления действительно висят в потоке пользовательского интерфейса, поскольку сообщения диспетчера попадают в очередь в ожидании завершения.

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

Пожалуйста, помогите мне найти правильный инструмент или какой-либо способ создания сложного, но очень отзывчивого пользовательского интерфейса WPF. Это Dispatcher.PushFrame()?

1 ответ

При таком количестве обновлений в секунду вы будете получать сообщения об обновлениях "в резервной копии" в очереди, поэтому ваши фоновые рабочие обновления блокируются.

Чтобы решить эту проблему, вам нужно регулировать количество создаваемых событий обновления.

Я бы использовал такой подход:

В моих ViewModels замените обычную реализацию INotifyPropertyChanged вызовом одноэлементного объекта, который будет отправлять уведомление от имени этого объекта.

private void OnPropertyChanged(string propertyName)
{
    PropertyChangedNotifier.Notify(this, propertyName, propertyChanged);
}

куда propertyChanged переменная-член, хранящая обработчики событий этих объектов

Notify Метод будет выглядеть примерно так:

public static void Notify(
    object sender, 
    string propertyName, 
    PropertyChangedEventHandler handlers)
{ ... }

В уведомителе не отправляйте событие немедленно - просто сохраните тот факт, что оно должно быть отправлено.

Если вы получаете уведомление несколько раз для одного и того же объекта / свойства, откажитесь от дополнительных уведомлений. Если вы получаете уведомление много раз для одного и того же объекта, но с разными свойствами, замените уведомление одним для всех свойств.

Теперь используйте таймер потока UX, чтобы "выпускать" уведомления каждые 50 мс или около того - все еще достаточно быстро, чтобы пользователь не заметил никакой разницы, и он выглядит как обновления в реальном времени, но достаточно медленно, чтобы обнаруживать (и удалять) дубликаты уведомлений.

Другие вопросы по тегам