Отправка потока насыщается - в поисках изменения шаблона дизайна от Vanilla MVVM - PullRequest
1 голос
/ 24 июня 2011

Возможно, «насыщенный» - неправильное слово, но по сути мой поток рассылки постоянно занят из-за большого количества обновлений пользовательского интерфейса, которые у меня есть.

До этого момента я следовал (и наслаждался) тому, что я бы назвал ванильным шаблоном MVVM-дизайна. Ключевые ресурсы, которыми я руководствовался при разработке, перечислены в превосходном принятом ответе на MVVM: учебное пособие от начала до конца .

В частности,

Грубая архитектура

У меня есть следующие пространства имен;

  • Данные
    • Подключается к внешней службе и прослушивает обновления
    • Получает пакет обновлений каждые 1-2 с
    • Один «Источник отправки», который планирует все обновления ViewModel в Диспетчере для приложения
  • ViewModel
    • Все классы, созданные в потоке пользовательского интерфейса, и все методы вызываются в потоке пользовательского интерфейса
    • Обрабатывает весь перевод данных в код GUI
  • Посмотреть
    • Xaml классы
    • Очень маленький (если есть) код позади или логика преобразования
    • Только тяжеловесный компонент - XCeed DataGrid , который сортирует данные внутри

Набор данных

На своем пике источник диспетчеризации планирует 65 000 событий в потоке диспетчеризации в минуту.

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

Проблема

Я полагаю, это уже очевидно, но отзывчивость очень плохая Иногда пользовательский интерфейс полностью блокируется.

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

Есть ли хороший шаблон проектирования для такой ситуации?

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

Многие и легкие против редких и тяжелых

Вместо 1000 с отдельных обновлений (вызовов методов), отправляемых в потоке пользовательского интерфейса, каждое из которых изменяет 4 привязки, я мог как-то внести изменения в фоновом потоке, а затем обновить 4000 привязок в пакетном методе, который выполняется в потоке пользовательского интерфейса.

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

Итог

Я в растерянности, что делать, я чувствую, что мне нужно внести все изменения в объекты в фоновом потоке, а затем опрашивать состояние с интервалом (каждые две секунды?), Чтобы пользовательский интерфейс оставался отзывчивым.

Это не похоже на MVVM, который я знаю и люблю, хотя. Есть ли подходящий способ привязки к набору данных, который изменяется с такой скоростью?

Ответы [ 2 ]

2 голосов
/ 24 июня 2011

Вы можете создать вашу базовую / корневую ViewModel, к которой все привязано, и заставить ее реализовать INotifyPropertyChanged - но запускать только PropertyChanged события, используя таймер, если какие-либо свойства изменились.

При изменении свойства -> добавить его в уникальный «грязный» список. Таймер истекает -> запускать все события в этом списке, сбросить список.

1 голос
/ 24 июня 2011

Кирен Джонстон на правильном пути.Я думаю, что ответ может быть еще проще, совсем не требуя таймера.

Реализуйте приведенные ниже члены в базовом классе модели представления.Установите службу данных на SuppressPropertyChanged для объектов модели представления в начале ее обновлений и очистите ее, когда она будет завершена.

protected void OnPropertyChanged(string propertyName)
{
   if (SuppressPropertyChanged)
   {
      return;
   }
   PropertyChangedEventHandler h = PropertyChanged;
   if (h != null)
   {
      h(this, new PropertyChangedEventArgs(propertyName);
   }
}

private bool _SuppressPropertyChanged;

public bool SuppressPropertyChanged
{
   get { return _SuppressPropertyChanged; }
   set
   {
      if (_SuppressPropertyChanged != value)
      {
         _SuppressPropertyChanged = value;
         if (!_SuppressPropertyChanged)
         {
            PropertyChangedEventHandler h = PropertyChanged;
            if (h != null)
            {
               // using null tells the listener to refresh all properties
               h(this, new PropertyChangedEventArgs(null);
            }
         }
      }
   }

Трудно сказать, не зная больше о вашем приложении.Если это сработает с тысячами привязок, вы можете захотеть сохранить HashSet<string>, который содержит имена свойств, которые изменились, когда уведомление об изменении свойства было подавлено, и выполнять итерацию по набору, когда подавление отключено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...