2010-09-08 8 views
2

Этот вопрос является уточнением моего вопроса Different ways of observing data changes.Лучший способ обновить пользовательский интерфейс?

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

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

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

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

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

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

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

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

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

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

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

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

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

Любая идея?

+0

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

ответ

2

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

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

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

+0

Хорошая идея. Что приятно, что он четко отделяет часть бизнес-логики (которая вообще не знает какого-либо пользовательского интерфейса) от части пользовательского интерфейса. – Patrick

0

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

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

  • ли работа
  • Commit

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

Это имеет тот недостаток, заставляя переписать код ...

0

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

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

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

Смежные вопросы