Обработчик простоя Delphi срабатывает только при перемещении мыши - PullRequest
3 голосов
/ 01 апреля 2011

В моем приложении D2006 есть обработчик OnIdle. С этим кодом:

procedure TMainForm.ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);

begin
Inc (IdleCalls) ;
Sleep (10) ;
Done := False ;
end ;

приложение работает без сбоев, обработчик простоя вызывается 100 раз в секунду, а загрузка ЦП близка к нулю.

Затем я добавил TActionList и соединил некоторые элементы управления с действиями, закодировал обработчик Execute и Update.

procedure TMainForm.ActionNewButtonExecute(Sender: TObject);
begin
DoNewProject ;
end ;

procedure TMainForm.ActionNewButtonUpdate(Sender: TObject);
begin
ActionNewButton.Enabled := AccessLevelIsSupervisor ;
end;

Проблема. Событие OnUpdate не срабатывает. На догадку я установил Done: = true в обработчике OnIdle, и обработчик OnIdle вызывается только при перемещении мыши. И действие Обновить все еще не запускается.

Почему обработчик обновлений не запускается, и я должен установить для Done значение true или false? Или оба?

Ответы [ 3 ]

6 голосов
/ 01 апреля 2011

Используйте источник, Люк.:)

Посмотрите на единицу Forms, в частности TApplication.Idle.Он частично содержит следующее:

Done := True;
try
  if Assigned(FOnIdle) then FOnIdle(Self, Done);
  if Done then
    if FActionUpdateDelay <= 0 then
      DoActionIdle
  // Excluded to avoid copyright violation
  // See also the else portion, which contains (in part)
  else
    if IdleTimerHandle = 0 then
    begin
      IdleTimerHandle := SetTimer(0, 0, FActionUpdateDelay, IdleTimerDelegate);
      if IdleTimerHandle = 0 then
        DoActionIdle
    end;
finally
  // Omitted
end;

Как видите, DoActionIdle вызывается только когда Done = True and FActionUpdateDelay <= 0 или IdleTimerHandle = 0.DoActionIdle (также часть TApplication) - это то, что называется UpdateAction.Поэтому, если ни одно из указанных выше условий не выполняется, TAction.OnUpdate никогда не вызывается.

Существует отдельный метод TApplication.DoMouseIdle, который вы также можете захотеть просмотреть.

3 голосов
/ 01 апреля 2011

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

Однако вы можете снизить загрузку ЦП без особых неприятных эффектов:
После обработки всех событий OnIdle приложение будет вызывать WaitMessage (которое будет бездействовать, пока очередь сообщений пуста), если Done параметр равен True - вы можете просто безоговорочно установить его в свой обработчик.

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

2 голосов
/ 01 апреля 2011

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

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

Мой совет заключается в следующем, потому что, как вы видите, этот способ действий мешает другим частямваше приложение.Если это ошибка в TApplication, я не знаю, может быть, это так.Если вы хотите больше исследовать, сделайте копию своего проекта, проверьте все, и если вы думаете, что это должно работать по-другому, заполните запись QC об этом.

Я искал исходный код XE и, похоже, Ok, они установили событие для обновления действий, если событие Idle не выполнено ... Я не вижу там ошибки.У меня нет готовых до 2010 года установок для проверки старых версий.

...