アイドリング ループ処理
多くのアプリケーションは、時間のかかる処理を "バックグラウンドで" 実行します。そのような処理にマルチスレッドを使用することは、パフォーマンスへの配慮が要求される場合があります。 スレッド処理は、開発のオーバーヘッドが大きくなるため、MFC が OnIdle 関数で行うアイドル時の処理のような単純なタスクにはおすすめできません。 この記事では、アイドル処理について重点的に取り上げます。 マルチスレッドについて詳しくは、マルチスレッドに関するトピックを参照してください。
ある種のバックグラウンド処理は、ユーザーがアプリケーションを対話的に操作していない間に適切に行われます。 Microsoft Windows オペレーティング システム向けに開発されたアプリケーションでは、時間のかかるプロセスを多数の小さなフラグメントに分割することでアイドル時の処理を実行できます。 アプリケーションは、各フラグメントの処理後、PeekMessage ループを使用して実行制御を Windows に戻します。
この記事では、アプリケーション内でアイドル処理を行う 2 とおりの方法について説明します。
MFC のメイン メッセージ ループで PeekMessage を使用する。
アプリケーション内の他の場所に別の PeekMessage ループを埋め込む。
MFC メッセージ ループ内の PeekMessage
MFC を使って開発されたアプリケーションでは、PeekMessage Win32 API を呼び出すメッセージ ループが、CWinThread
クラスのメイン メッセージ ループに存在します。 このループではさらに、CWinThread
のメンバー関数 OnIdle
が、メッセージとメッセージの間に呼び出されます。 OnIdle
関数をオーバーライドすることで、アプリケーションがこのアイドル時間にメッセージを処理できるようになります。
Note
現在、Run
や OnIdle
など特定のメンバー関数は、CWinApp
クラスではなく CWinThread
クラスのメンバーとなっています。 CWinApp
は、CWinThread
から派生しています。
アイドル処理の実行について詳しくは、"MFC リファレンス" の OnIdle に関するセクションを参照してください。
アプリケーション内の他の場所に埋め込まれた PeekMessage
アプリケーションでアイドル処理を行うもう 1 つの方法は、いずれかの関数にメッセージ ループを埋め込むものです。 このメッセージ ループは、CWinThread::Run に見られる MFC のメイン メッセージ ループによく似ています。 つまり、MFC で開発されたアプリケーションのそのようなループは、メイン メッセージ ループが果たす役割の多くを行う必要があります。 次のコード フラグメントは、MFC と互換性のあるメッセージ ループを実際に作成する例です。
BOOL bDoingBackgroundProcessing = TRUE;
while (bDoingBackgroundProcessing)
{
MSG msg;
while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!AfxGetApp()->PumpMessage())
{
bDoingBackgroundProcessing = FALSE;
::PostQuitMessage(0);
break;
}
}
// let MFC do its idle processing
LONG lIdle = 0;
while (AfxGetApp()->OnIdle(lIdle++))
;
// Perform some background processing here
// using another call to OnIdle
}
このコードは関数に埋め込まれており、実行するアイドル処理が存在する限りループします。 そのループ内では、入れ子になったループによって繰り返し PeekMessage
が呼び出されます。 その呼び出しからゼロ以外の値が返される限り、CWinThread::PumpMessage
を呼び出して、通常のメッセージ変換とディスパッチを実行します。 PumpMessage
はドキュメント化されていませんが、Visual C++ インストール ディレクトリの \atlmfc\src\mfc の ThrdCore.Cpp ファイルで、そのソース コードを観察することができます。
内側のループが終了すると、外側のループで、OnIdle
が 1 つまたは複数呼び出されてアイドル処理が実行されます。 1 つ目の呼び出しは MFC 用です。 さらに OnIdle
の呼び出しを追加することで、独自のバックグラウンド処理を実行することができます。
アイドル処理の詳細については、MFC ライブラリ リファレンスの OnIdle に関するセクションを参照してください。