解決マークを付けさせていただきますと言っておいてチェックしていませんでした(恥)。
よろしくお願いします。
スレッドの終了確認にはイベントを使用するのが通常ですが、
簡略に済ませたい場合、かつ、ローカルに済ませたい場合、
自分はDLG、スレッドが両方ともなくなっても存在している
オブジェクト内にvolatileのフラグを用意してこれで判定しています。
>現在のところは、ワーカスレッドを終了する直前でフラグを立てておいて
の「フラグ」はvolatileであるべきです。
でないと、リリースビルド時にキャッシュされた「フラグ」が
参照されてしまい、うまく働がない場合がありえます。
>ワーカスレッド自身がフラグを立てた直後はまだ終了していない状態ですから、
>スレッド切り替えのタイミングによっては、終了していない状態で
>ダイアログ側が終了したと判断してしまうのかなと疑問に思っています。
開始処理と同様、スレッドの終了処理が開始されてしまうと終了処理を完了
するまでは、原理的に他のスレッドに切り替えられないはずです。
スレッド関数のリターン直前の「フラグ」設定は、事実上スレッドの
最後の処理と同意です。
俺はいつも
・bAutoDelete=FALSE とする (そのためには CREATE_SUSPENDED を使う)
・基本的にスレッド終了チェックは不要なように作る
すなわち、スレッドが終了するまで絶対に Dlg や WND が消滅しないように作る
・チェックが必要であるなら WaitForSingleObject(スレッド, 0) でチェック
としているよん。
私の場合ですが、基本的にウインドウメッセージで通知するのは
タイミングのみで具体的な情報はグローバル領域に作った
共有データクラスのインスタンスで引き渡します。
共有データクラスは、内部にやり取りするデータを保持していて
取り出しと設定はクラスメソッドでやります。
メンバー変数は勿論private変数です。
クリティカルセクションを使って排他処理行い。
データを扱う側は意識しなくて良いようにします。
あと、Postによって通知されるのはあくまでも終了するよという
通知です。勿論、それを受けたメインスレッドはワーカースレッドの
終了をスレッドハンドルで監視します。
ここが終了の待ち合わせになります。
ワーカースレッドが完全に終了している状態を確認する場合、
そのようにします。
この辺のやり取りは、CWinThreadのm_bAutoDeleteをFALSEして
あくまでもスレッドのオブジェクトの破棄はメインスレッドで
やると言うスタンスになります。
私自身としてはワーカースレッドの状態(存在とか動作中等)は、
メインスレッドが完全に把握している状態にしようとします。
これは、ワーカースレッド動作中にアプリを終了させるような場合に
ワーカースレッドの終了を待ち合わせて必要な終了処理を行う為にも
必要な事だと考えています。
仲澤@失業者さん、tetrapodさん、PATIOさん、
引き続き解説いただきありがとうございます。
> 開始処理と同様、スレッドの終了処理が開始されてしまうと終了処理を完了
> するまでは、原理的に他のスレッドに切り替えられないはずです。
> スレッド関数のリターン直前の「フラグ」設定は、事実上スレッドの
> 最後の処理と同意です。
これはつまり、フラグを立ててから直後に死ぬまでの間に
UIスレッド側に切り替わってその立ったフラグを見てしまうことは、
原理的には無いということになるのですね。
となると、フラグをタイマで監視する方法も、
UIスレッド側にPostMessage()で終了を伝える方法も、
原理上は2つの引数のまま(m_bAutoDelete=TRUEのまま)
ワーカスレッドを開始しても問題無いのかなと感じますが、
tetrapodさんもPATIOさんもm_bAutoDeleteはFALSEにされているのですね。
終了したのを知りたいだけでなく、高度な監視をしようとすると、
やはりスレッドのハンドルは持っておいたほうがよいということですよね。
じっくり勉強させていただきます。
みなさんありがとうごうざいました。