アイドリング ループ処理
更新 : 2007 年 11 月
多くのアプリケーションでは、時間のかかる処理を "バックグラウンド" で行います。パフォーマンスを考慮して、このような処理にはマルチスレッドを使用することもあります。しかし、スレッドは、開発の余分なオーバーヘッドを伴うため、MFC が OnIdle 関数で行うアイドリング タスクのような単純なタスクには向きません。ここでは、アイドル処理を中心に説明します。マルチスレッドの詳細については、「マルチスレッド」を参照してください。
ユーザーがアプリケーションと対話していないときに行われるバックグラウンド処理もあります。Microsoft Windows オペレーティング システム対応のアプリケーションでは、長い処理は多数の小さな断片に分割されて、アイドル時に処理されます。アプリケーションは、各断片の処理後に PeekMessage ループを使用して実行制御を Windows に委ねます。
ここでは、アプリケーションでアイドル処理を行う 2 つの方法を説明します。
MFC のメイン メッセージ ループで PeekMessage を使用する。
アプリケーションの別のどこかに PeekMessage ループを埋め込む。
MFC メッセージ ループ内の PeekMessage
MFC を使用して開発されたアプリケーションでは、CWinThread クラスのメイン メッセージ ループ内に PeekMessage Win32 API を呼び出すメッセージ ループが含まれます。このループでも、メッセージ間で CWinThread の OnIdle メンバ関数を呼び出します。OnIdle 関数をオーバーライドすると、アプリケーションはこのアイドル時間中にメッセージを処理できます。
メモ : |
---|
Run、OnIdle などの特定のメンバ関数は、CWinApp クラスのメンバではなく、CWinThread クラスのメンバになっています。CWinApp は、CWinThread の派生クラスです。 |
アイドル処理の詳細については、『MFC リファレンス』の OnIdle に関する説明を参照してください。
アプリケーション内の異なる場所の PeekMessage
アプリケーションでアイドル処理を行うには、いずれかの関数にメッセージ ループを埋め込むという方法もあります。このメッセージ ループは、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 を繰り返し呼び出します。この呼び出しが 0 以外の値を返す限り、ループは CWinThread::PumpMessage を呼び出し、通常どおりにメッセージの変換とディスパッチを行います。PumpMessage の詳細は公開されていませんが、そのソース コードは Visual C++ をインストールしたディレクトリの \atlmfc\src\mfc にある ThrdCore.Cpp ファイルで確認できます。
内部のループが終了すると、外部のループは OnIdle を呼び出してアイドル処理を実行します。最初の呼び出しは MFC の目的に従って行われます。2 回目以降の OnIdle の呼び出しでは、独自のバックグラウンド処理を行うことができます。
アイドル処理の詳細については、『MFC リファレンス』の OnIdle に関する説明を参照してください。