Лучший способ поддерживать пользовательский интерфейс в актуальном состоянии? - PullRequest
2 голосов
/ 08 сентября 2010

Этот вопрос является уточнением моего вопроса Различные способы наблюдения за изменениями данных .

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

Если я использую подход «наблюдателя» и отправляю уведомления каждый раз при изменении значения экземпляра, у меня есть 2 больших риска:

  • Сама отправка уведомлений может серьезно замедлить работу приложений
  • Если элементы пользовательского интерфейса должны быть обновлены при изменении, они обновляются при каждом изменении, что приводит, например, к экранамобновляется три раза во время выполнения некоторой части бизнес-логики

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

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

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

Оба подхода имеют похожие, но противоположные недостатки:

  • СПри использовании подхода «наблюдателя» мы рискуем обновить пользовательский интерфейс слишком много раз
  • При использовании подхода «очень грязный» мы рискуем вообще не обновлять пользовательский интерфейс

Оба недостатка можно решить, внедрив каждое действие приложения в дополнительную логику (для наблюдателя).s: отправка начальных и конечных уведомлений, для mark-dirty: отправка уведомлений об обновлении самостоятельно).

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

Однако,для оконных приложений нет никаких сигналов о том, что пользователь «смотрит на ваш экран» и что окна должны быть обновлены.Таким образом, нет действительно хорошего момента, когда вы должны смотреть на грязные данные (хотя вы могли бы сделать некоторые фокусы с событиями фокуса).

Что является хорошим решением для решения этой проблемы?И как вы решили подобные проблемы в своем приложении?

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

Есть идеи?

Ответы [ 3 ]

2 голосов
/ 08 сентября 2010

Несколько лет назад я использовал подход с большим приложением для Windows - использовать WM_KICKIDLE. Все вещи, которые могут обновляться, используют абстрактный базовый класс с именем IdleTarget. IdleTargetManager затем перехватывает сообщения KICKIDLE и вызывает обновление в списке зарегистрированных клиентов. В вашем случае вы могли бы создать список конкретных целей для обновления, но я нашел список зарегистрированных клиентов достаточно.

Единственная ошибка, с которой я столкнулся, была с графиком в реальном времени. Если использовать только сообщение о простое, это увеличит нагрузку на процессор до 100% из-за постоянного обновления графика. Используйте таймер для сна, пока следующее обновление не решит эту проблему.

Если вам нужна дополнительная помощь - я доступен по разумным ценам ...: -)

0 голосов
/ 08 сентября 2010

Вы можете использовать шаблон наблюдателя с объединением. Хотя это может быть немного уродливо для реализации в C ++. Это будет выглядеть примерно так:

m_observerList.beginCoalescing();
m_observerList.notify();
m_observerList.notify();
m_observerList.notify();
m_observerList.endCoalescing(); //observers are notified here, only once

Таким образом, даже если вы звоните notify три раза, наблюдатели фактически не уведомляются до endCoalescing, когда наблюдатели уведомляются только один раз.

0 голосов
/ 08 сентября 2010

Еще один момент, о котором я думал.

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

  • Сделай работу
  • Commit

где уведомления отправляются только при коммите.

У него есть недостаток в том, что он заставляет переписывать некоторый код ...

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