マルチスレッド: MFC でのスレッドの終了
通常、スレッドは、次の 2 つの条件で終了します。1 つは制御関数が終了した場合、もう 1 つはスレッドを最後まで実行できなかった場合です。 ワード プロセッサでバックグラウンド印刷用のスレッドを使っている場合、印刷が正常に終了すると、制御関数が正常に終了します。 ただし、ユーザーが印刷をキャンセルするときは、バッググラウンド印刷用のスレッドを途中で終了する必要があります。 このトピックでは、この 2 つの終了処理を実現する方法と、スレッド終了時の終了コードを取得する方法について説明します。
通常のスレッド終了
ワーカー スレッドでは、スレッドの正常終了は単純です。制御関数を終了し、終了理由を呼び出し元に返すだけです。 これには、AfxEndThread 関数を使うことも、return
ステートメントを使うこともできます。 通常、0 を返して正常終了を通知しますが、返す値はプログラマが決めることができます。
ユーザー インターフェイス スレッドの場合も、そのプロセスは同じように簡単です。ユーザー インターフェイス スレッド内から、Windows SDK の PostQuitMessage を呼び出します。 PostQuitMessage
が受け入れるパラメーターは、スレッドの終了コードだけです。 ワーカー スレッドの場合と同じように、通常は 0 を返して正常終了を通知します。
スレッドの早期終了
スレッドの中断もほとんど同じように単純です。終了するスレッドから AfxEndThread を呼び出すだけです。 パラメーターは終了コードだけです。 この関数はスレッドの実行を停止し、スレッドが占有していたスタック領域を解放し、スレッドにアタッチしているすべての DLL をデタッチし、メモリからスレッド オブジェクトを削除します。
関数 AfxEndThread
は終了するスレッドから呼び出します。 あるスレッドを別のスレッドから終了させるには、2 つのスレッド間の通信メソッドを設定する必要があります。
スレッドの終了コードの取得
スレッドの終了コードを取得するには、ワーカー スレッドの場合も、ユーザー インターフェイス スレッドの場合も、GetExitCodeThread 関数を呼び出します。 この関数の詳細については、Windows SDK を参照してください。 この関数は、CWinThread
オブジェクトの m_hThread
データ メンバーに格納されている、スレッドへのハンドルと、ダブルワードのアドレスを受け取ります。
スレッドがまだアクティブな場合、GetExitCodeThread
は、渡されたダブルワード型のアドレスで STILL_ACTIVE を返します。それ以外の場合は、このアドレスで終了コードを返します。
CWinThread オブジェクトの終了コードを取得するには、さらに操作が必要です。 既定では、CWinThread
スレッドが終了すると、このスレッド オブジェクトが削除されます。 つまり、m_hThread
オブジェクトがもう存在しないので、CWinThread
データ メンバーにはアクセスできません。 この状況を回避するには、以下のいずれかの操作を実行します。
m_bAutoDelete
データ メンバーを FALSE に設定します。 これにより、CWinThread
オブジェクトは、スレッドが終了した後も残ります。 次に、スレッドが終了した後で、m_hThread
データ メンバーにアクセスできます。 ただし、この方法を使用すると、フレームワークではCWinThread
オブジェクトが自動的に削除されないため、このオブジェクトを直接破棄する必要があります。 可能であればこの方法の使用をお勧めします。スレッドへのハンドルを別に保存します。 スレッドの作成後、この
m_hThread
データ メンバーを::DuplicateHandle
で別の変数にコピーし、この変数を通じてデータ メンバーにアクセスします。 この方法では、スレッドの終了時にオブジェクトが自動的に削除され、スレッドが終了した理由もわかります。 この場合、スレッドを終了しないと、ハンドルを複製できません。 最も安全な方法は、AfxBeginThread に CREATE_SUSPENDED を渡してスレッドを停止状態にし、ハンドルを格納してから、ResumeThread を呼び出してスレッドを再開します。
この方法のどちらかを使うと、CWinThread
オブジェクトの終了理由を判定できます。
関連項目
C++ と MFC を使用するマルチスレッド
_endthread、_endthreadex
_beginthread、_beginthreadex
ExitThread