3

D2006アプリにOnIdleハンドラーがあります。このコードで:

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

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

アプリはスムーズに実行され、アイドルハンドラーは1秒間に100回呼び出され、CPU使用率はほぼゼロです。

次に、TActionListを追加し、いくつかのコントロールをアクションに接続し、実行および更新ハンドラーをコーディングしました。

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

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

問題。OnUpdateイベントは発生しません。思い切って、OnIdleハンドラーでDone:= trueを設定すると、マウスを動かしたときにのみOnIdleハンドラーが呼び出されます。そして、更新アクションはまだ起動しません。

Updateハンドラーが起動しないのはなぜですか?Doneをtrueまたはfalseに設定する必要がありますか?または両方?

4

3 に答える 3

6

ソース、ルークを使用してください。:)

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でのみ呼び出されます。(これもTApplicationの一部です)は、と呼ばれるものです。したがって、上記の条件のいずれも満たされない場合、TAction.OnUpdateは呼び出されません。Done = True and FActionUpdateDelay <= 0IdleTimerHandle = 0DoActionIdleUpdateAction

別の方法がありTApplication.DoMouseIdleますが、これもよく読んでください。

于 2011-03-31T23:45:43.763 に答える
3

コメントで述べたようにSleep、アイドルハンドラーでは効果がなく、アプリケーションでアクティビティがない場合は、bacground処理も停止します。

ただし、邪魔な影響をあまり受けずにCPU使用率を下げることができます。
すべてのイベントを処理した後、パラメータが-の場合OnIdle、アプリケーションは呼び出しますWaitMessage(メッセージキューが空のときにスリープします)。ハンドラーで無条件に設定できます。DoneTrue

バックグラウンド処理については、スレッドを使用してメインスレッドにコールバックするSynchronizeか、本当に必要な場合はタイマーを使用して、再入可能性を処理することを忘れないでください(どちらのソリューションもアプリケーションをウェイクアップします) while WaitMessage)。

于 2011-04-01T11:20:08.550 に答える
2

そのOnIdleイベントハンドラーを取り除きます。念のためにそこにあることを受け入れまし

後でバックグラウンドタスクを実行する必要がある場合は、スレッドの使用方法を学習してください。特定の頻度を取得するには、スレッド内でスリープまたはその他の手法を使用できます。

ご覧のとおり、この方法はアプリケーションの他の部分に干渉しているため、私のアドバイスはこのようになっています。TApplicationのバグであるかどうかはわかりませんが、おそらくそうです。さらに調査したい場合は、プロジェクトのコピーを作成し、すべてをチェックしてください。これが別の方法で機能する必要があると思われる場合は、それに関するQCエントリに記入してください。

XEのソースコードを探していたところ、問題ないようです。アイドルイベントが実行されない場合、アクションを更新するイベントが設定されています。バグはありません。古代のバージョンをチェックするための2010年以前のインストールがありません。

于 2011-04-01T02:25:50.740 に答える