非アクティブな状態が一定時間続いた後、ユーザーをアプリケーションからログアウトさせたい。
非アクティブのチェックをアプリケーションのOnIdleハンドラーまたはタイマーハンドラーに入れる方がよいでしょうか?
粒度はそれほど重要ではありません。ログアウトはプラス/マイナス数秒、場合によっては1分になることもあります。
アプリのOnIdleが頻繁に起動するように感じます。何かアドバイス?コード自体はほんの数行です。
非アクティブな状態が一定時間続いた後、ユーザーをアプリケーションからログアウトさせたい。
非アクティブのチェックをアプリケーションのOnIdleハンドラーまたはタイマーハンドラーに入れる方がよいでしょうか?
粒度はそれほど重要ではありません。ログアウトはプラス/マイナス数秒、場合によっては1分になることもあります。
アプリのOnIdleが頻繁に起動するように感じます。何かアドバイス?コード自体はほんの数行です。
GetLastInputInfo を使用してアイドル時間を測定しています。それは非常に理にかなっているようです。したがって、質問は要約すると
OnIdle ハンドラーまたはタイマーで定期的なチェックを行う必要がありますか?
OnIdle は、メッセージ キューが空になるたびに発生します。キューにメッセージが配置されていない場合、OnIdle は起動しません。そのため、OnIdle は定期的ではありません。非アクティブ状態を定期的にチェックする何かが必要な場合は、OnIdle が機能しない可能性があります。タイマーは確実に作動します。
次のように考えることができます: アイドル カウンターが開始すると OnIdle イベントが発生しますが、アイドル カウンターが期限切れになったときに発生するイベントが必要です。
アプリの OnIdle が頻繁に起動するように感じます。
実際、あなたの問題はこれの反対です!
これを試してみると、OnIdle が適切に機能しているように見え、定期的に起動することに注意してください。たとえば、アプリでタイマーを使用している場合、OnIdle は各タイマー イベントの後に発生します。タイマー イベントがキューに入って処理されると、OnIdle が発生します。ただし、アプリにタイマーがない場合、プログラムとの対話を停止すると、OnIdle がまったく起動しないことが期待できます。
個人的には以下を使っています。
GetLastInputInfo は Windows からのもので、キーボードまたはマウスのアクティビティがなかった時間の長さを示す結果を提供します。
TimerLogoffTimer は、5 秒ごとにトリガーするように設定されたタイマーです。
TimeoutValue は、構成から読み取った値です
DoLogoff は、フォームを閉じるなどの実際の作業を行うプロシージャです。
function SecondsIdle: DWord;
var
liInfo: TLastInputInfo;
begin
liInfo.cbSize := SizeOf(TLastInputInfo) ;
GetLastInputInfo(liInfo) ;
Result := (GetTickCount - liInfo.dwTime) DIV 1000;
end;
procedure TfrmMain.TimerLogoffTimer(Sender: TObject);
begin
if SecondsIdle >= DWord(TimeoutValue) then
DoLogoff;
end;
OnIdle と TTimer の問題は、数日前にエンバカデロ フォーラムで議論されました。
特に、そのディスカッションでの私の返信TApplication.OnIdle
は、イベントが実際にどのように機能するか、および設定Done
パラメーターが実際に何を意味するかを説明しています。
OnIdle は、アプリケーションがアイドル状態になったときに 1 回だけ呼び出されることを理解しています。
アプリケーションが新しいアイドル状態に入るたびに呼び出されます。メイン メッセージ ループがメイン メッセージ キューからメッセージを取得しようとするたびに、まだメッセージが存在しない場合、OnIdle イベントがトリガーされ、メイン スレッドは新しいメッセージがキューに到着するまでスリープ状態になります。メッセージが処理されてキューが再び空になると、OnIdle イベントが再びトリガーされ、メイン スレッドは新しいメッセージが到着するまでスリープ状態になります。
これを使用すると、チェック手順が 1 回だけ呼び出され、システムは再度チェックせずにユーザー入力を待ち続けます。
OnIdle イベント ハンドラでは、Done パラメータを False に設定して、処理するメッセージがない場合にメイン スレッドがスリープ状態にならないようにすることができます。これにより、キューに新しいメッセージがない間、OnIdle イベントをトリガーし続けることができます。ただし、これには TAction.OnUpdate イベントを無効にするという副作用があります。
私がやりたいのは、タイマーの表示を更新することです。
次に、タイマーが経過するたびに UI を更新するリアル タイマー広告を使用する必要があります。
残り時間が変化するにつれて、継続的に再描画する必要があります。おそらく、これを行うには、よりシンプルで優れた別の簡単な方法があります。
TTimer コンポーネントとその OnTimer イベントを見てください。
Windows にこれを行わせてみませんか?
ユーザーが作業を再開したい場合に、スクリーンセーバーを自動的に開始してログオンを強制するポリシーがあります。
Windows 7 の時点では、カフェインやその他のキーボード シミュレーターなどのツールを使用してそれらを回避することはできません。
これにより、Delphi アプリ内から実行できることよりもはるかに厳密になります。
TTimer は Windows の内部リソースを使用しますが、これは今日のギガヘルツとギガバイトの世界では大したことではないかもしれませんが、それでも良くありません。
OnIdle または MainForm.Action を使用してみます - http://docwiki.embarcadero.com/Libraries/en/System.Classes.TBasicAction.OnUpdate
この両方のアプローチは、おそらく少し減速する必要があります - http://docwiki.embarcadero.com/Libraries/en/Vcl.Forms.TApplication.ActionUpdateDelay
ただし、TApplication.OnIdle に関するこれらの行に注意してください。これは、各ループの後にアプリケーションに stup no-op メッセージをポストするセルフチェーン イベントである可能性があります。
Done パラメータが false に設定されていない限り、連続して呼び出されることはありません。Done を false に設定したアプリケーションは、CPU 時間を大量に消費し、システム全体のパフォーマンスに影響を与えます。