• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:[VC++] AfxBeginThreadで生成したスレッドの監視方法について)

[VC++] AfxBeginThreadで生成したスレッドの監視方法について

このQ&Aのポイント
  • VC++でAfxBeginThreadを使用して生成したスレッドの監視方法について質問です。
  • 問題は、ワーカースレッドが処理状態になったことをメインスレッドで検知できないことです。
  • Sleep(0)をAfxGetApp()->PumpMessage()に変更すると問題が解決するようですが、納得できません。

質問者が選んだベストアンサー

  • ベストアンサー
  • MrBan
  • ベストアンサー率53% (331/615)
回答No.2

失礼。 CTestDlg dlg;がメインにあるというよりも、 問題はpDlg->Create(TestDlg::IDD);こっちぽいですね。 CTestDlgがMFCのダイアログの派生だとすると、 Create時に親を指定しない場合(このケースはそう)、 親ウィンドウがメインウィンドウ(メインスレッド側)になりますので、 ウィンドウ破棄の時に親側がただしく処理されてない、と。 # MFCのウィンドウは内部にTLSなど使ってるので、むやみにスレッドを # 跨がせると危険なため、一見そちらかと思いましたが別原因ぽい。 > あと、OnTestはコールバックでなく > メインスレッド側の単なるコマンド実行の関数です。 > 説明不足ですみません。 ここでは、メインスレッドのメッセージポンプを止めるか否かが焦点ですので、 Test用ボタンが押されたときに動くとか、Menuが押されたときに動くとか、 MFCのウィンドウメッセージで動くものは、 内部処理はWin32のWindow Procedureから呼ばれるコールバックの一種です。 # 基本的にMFC関係のウィンドウ自体は全部メインスレッドにしないと、 # 処理のたびに内部でスレッド内にまたがった同期が発生したりしますので、 # そもそもメインで安易にwhileしないとか、実処理だけをワーカにするなど検討させることをお勧めします。 # ・ワーカ側にDlgを直接渡す必要性は普通ないです。 # ・ワーカでCreateなんてのも普通しません。(せめてUIスレッドならまだしも) # ・ダイアログをメインで作って、内部処理だけワーカで行ってもお望みのことはできます。 # ・設計上、UIと内部処理は極力分離するのが好ましいです。

mavosuke
質問者

お礼

MrBanさん 詳しい回答をいただきまして ありがとうございます。 確かに、pDlg->Create(TestDlg::IDD); を実行したときに、処理がとまっていました。 ワーカースレッドの中で、ダイアログ生成~破棄するのを やめて、メインスレッドに移すとうまく動くようになりました。 CWnd* と HWND のパーマネントマップがスレッドごとに 異なるため、スレッドを跨いで親ウィンドウにアクセスすると ハングしてしまうようですね。 今後は極力、ワーカスレッドにはウィンドウを渡さない 設計でプログラムしようと思います。 アドバイスをいただきまして まことにありがとうございました。

その他の回答 (1)

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.1

> pDlg->DestroyWindow(); 多分これのせいです。 > CTestDlg dlg; をメイン側においてるので、メイン側のスレッドコンテキストでウィンドウが動いてると思われます。 ワーカ側でウィンドウを破棄しようとすると、 メイン側のメッセージ処理が動く必要がありますが、 メイン側はOnTestという(恐らく)コールバック内でループしているため、 メッセージが処理されずに止まってしまいます。 PumpMessageにするととりあえず内部でメッセージが処理されるので、 破棄されるようになると思いますが、正直あまりお勧めの処理とはいえません。 # MFCのウィンドウはスレッド跨ぎで処理するとハマルことがあったり、 # 念のためvolatileをつけておくべき、とか、 # メインスレッドでむやみにループするべきではない、とか、 # 根本的に気になる点もいくつかありますが…。

mavosuke
質問者

補足

MrBanさん。 回答をいただきましてありがとうございます。 >CTestDlg dlg; >をメイン側においてるので、メイン側のスレッドコンテキスト >でウィンドウが動いてると思われます。 確かに、dlgオブジェクトはメインスレッドにありますが、 ウィンドウの生成は pDlg->Create(TestDlg::IDD); でスレッド内で行っています。 そうするとウィンドウはスレッドコンテキストで 動くと思うのですが、間違っていますか? メイン側の TestDlg dlg; は、単なるオブジェクトをスタックに置いている だけのような気がするのですが、 これだけで、メインスレッド側でウィンドウが 動くことになるのでしょうか? あと、OnTestはコールバックでなく メインスレッド側の単なるコマンド実行の関数です。 説明不足ですみません。 よろしく、お願いいたします。

関連するQ&A

専門家に質問してみよう