Как сохранить отзывчивость приложения Delphi во время обновления графического интерфейса? - PullRequest
5 голосов
/ 02 февраля 2010

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

Я широко использую потоки и шаблон задачи для выполнения дорогостоящей задачи в фоновом потоке. Но как насчет обновлений GUI, которые занимают некоторое время? Например, заполнение большой строки сетки или дерева? Поток здесь не помогает, потому что все равно нужно синхронизировать с основным потоком.

Я знаю проблемы Application.ProcessMessages, но в настоящее время кажется, что это единственное решение для вызова ProcessMessages внутри методов обновления GUI.

Есть идеи получше?

Ответы [ 6 ]

5 голосов
/ 02 февраля 2010

IMO, если обновление GUI является узким местом (даже если BeginUpdate / EndUpdate используется, как подсказывает @The_Fox), тогда пришло время пересмотреть используемые элементы управления GUI. Стандартные сетки, древовидные структуры, списки не просто вырезаны для обработки очень большого количества элементов. Для этой цели существует множество эффективных сторонних средств управления, как бесплатных, так и коммерческих.

Для начала, проверьте VirtualTreeview, если узкое место находится в сетке, в виде дерева или в контексте списка.

5 голосов
/ 02 февраля 2010

При заполнении гридов, списков, наборов данных и т. Д. Вызывайте BeginUpdate / EndUpdate DisableControls / EnableControls. Это сэкономит вам время. У меня также был поток, который выполнял некоторые вычисления, но, тем не менее, графический интерфейс был медленным, пока я не вызвал DisableControls для наборов данных, которые были изменены и не видны, поскольку элементы управления находятся на другой вкладке.

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

4 голосов
/ 02 февраля 2010

Что не так с Application.ProcessMessages в вашем случае? Метод Application.ProcessMessages как раз для таких случаев. Проблема с Application.ProcessMessages заключается в следующем коде:

repeat
  Application.ProcessMessages;
until SomethingHappens;

Это плохо, так как это бесполезная загрузка процессора, и должна быть заменена на

repeat
  Application.HandleMessage;
until SomethingHappens;

, который уступает процессорное время другим потокам. Одиночные вызовы Application.ProcessMessages (не в цикле) в порядке.

1 голос
/ 02 февраля 2010

Если вы хотите обрабатывать только сообщения рисования и ничего больше: используйте вместо Application.ProcessMessages следующее:

procedure ProcessPaintMessages;
var
  Msg: TMsg;
  i: Integer;
begin
  i := 0;
  repeat
    if Windows.PeekMessage(Msg, 0, 0, 0, PM_REMOVE or (QS_PAINT shl 16)) then begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end else Break;
    Inc(i);
  until i > 1000; // Breakout if we are in a paint only loop!
end;
1 голос
/ 02 февраля 2010

Взгляните на ActiveSleep .

0 голосов
/ 02 февраля 2010

Вы пробовали компонент AntiFreeze от Indy?

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