もう終わった話だと思いますが...
僕は気分次第というか、ワーカースレッド用途でも両方使ってますね。
pfnThreadProcでやる場合でも
引数に専用の構造体を作らなきゃいけなくって、
それは自動変数にしちゃいけないとか、
終了監視するスレッドハンドルを取得するためにサスペンド指定が必要だとか、
そういうややこしくてバタバタになりがちなところを派生クラス側に全部持たせられるの
で結構便利だったり。
何故か新しくスレッドクラスを書いてその中で pfnThreadProc を使ってる人も
ちょくちょく見かけるけど、そんなことするなら CWinThread 派生使えば
いいんじゃないかとか...
何か、論戦していますね。
すみませんが、僕はDLL内でスレッド動かしたことないもので.......
もし、このスレッド内の処理にGUIが使われていないなら、
main()のなかで「AfxBeginThread」を使ってみたらどうでしょうか?
これでもだめなら、スレッド内の処理がおかしいと思います。
さて、僕もちょっと横から失礼します。
「AfxBeginThread」をMFCで使うと危険?
僕は、「AfxBeginThread」しか使ったことないです。
しかも、MFCのなかで、、、、、
大抵、スレッドは、「CMainFrame」のなかで作ります。
そして、スレッド中で「CMainFrame」のthisポインターを受け取って
「CMainFrame」内のメンバー関数を動かします。
別に危険でないです。
通信なんかも、別のクラス作って通信しています。
問題なく動作しています。
> そして、スレッド中で「CMainFrame」のthisポインターを受け取って
> 「CMainFrame」内のメンバー関数を動かします。
> 別に危険でないです。
MFC のウィンドウは、内部でTLS(スレッドローカルストレージ)を参照してたりして、
むやみに this とか渡すと危険/意図しない動作する可能性があるわけですが、
この認識はありますか。
また、設計がメッセージ同期前提なものは、this から関数呼び出しする際に別途
排他制御がいるかと思いますが、それらも考慮された上ですか。
> MFC のウィンドウは、内部でTLS(スレッドローカルストレージ)を参照してたりして、
> むやみに this とか渡すと危険/意図しない動作する可能性があるわけですが、
> この認識はありますか。
これって、それほど危険じゃないけどね。
俺の考え(場合)ではだけど。
TLSを参照しているのはウィンドウハンドルから
CWndポインタを逆引きするテーブルのことでしょ。
それとも他にある?
むしろ、逆に危険だと思っている。
thisを渡さず、ウィンドウハンドルを渡して、
ワーカスレッドでそのウィンドウハンドルからCWndポインタを得て、
CWndポインタをダウンキャストしてアクセスする方が危険じゃないのかな。
/*
無論 Banさんはそんなことしないでしょうけど。
this とか渡すと危険ってよく耳にするが、
じゃthis渡さなければいいんだってなって、
一時CWndポインタをダウンキャストする
やからが出没するんじゃないかと俺は懸念している。
*/
ワーカスレッドからウィンク関連の処理の呼び出しは危険だな。
そういった意味ではthisを渡さないほうが危険性は低い。
/*
thisを渡しても、thisを渡さなくても、
俺にとってワーカスレッドからウィンク関連の処理の呼び出しは厳重注意なんで、
ある意味thisを渡してもOK。ある意味thisを渡さなくても危険がいっぱい。
*/
でも、禁止するだけでは解決にならない。
thisの変わりに構造体を作り、
その構造体に情報をコピーしてスレッドのパラメタに渡すか、
CWinThreadの派生クラスに同様なことを施すんだろ。
でも、仕様変更とかあったりすること考えると憂鬱だな。
ところで具体的にどんな危険/意図しない動作する可能性があるんだろう。
無論そのときの状況によることであり、
CWinThreadの派生クラスを作ってはいけないといっているわけじゃないよ。
> this とか渡すと危険ってよく耳にするが、
> じゃthis渡さなければいいんだってなって、
> 一時CWndポインタをダウンキャストする
> やからが出没するんじゃないかと俺は懸念している。
そんなヤツいないよな(笑い)。
おれはMSDNのこれに関する説明はおかしいと考えている。
<引用>
この問題を解決する方法はいくつかあります。第 1 の方法は、ワーカー スレッドに
C++ オブジェクトを渡さずに HWND などのハンドルを個別に渡す方法です。ワーカー ス
レッドは該当するメンバ関数 FromHandle を呼び出して、テンポラリ マップにオブジェ
クトを登録します。関数 Attach では、オブジェクトをスレッドのパーマネント マップ
に登録できます。この方法は、オブジェクトがスレッドの消滅後も残存する場合以外は
使わないでください
</引用>
CWndじゃなくてC++オブジェクトは全部危険なのかよ~
FromHandle を呼び出すってのも判らん。
マップにテンポラリなオブジェクトを登録しても意味ないだろ。
ワーカスレッドのマップに本物のインスタンスを登録するには
そもそもスレッドにthisを渡さないと無理だろ。なんだそれそれあ~それそれ!
C++オブジェクトはだめっていっているし、HWNDしか使えないのかよ。
さらにAttachだとスレッドの消滅後も残存しちゃだめだって~
それもワーカスレッドより生存期間の長いオブジェクトばかりですよ。
使えね~
これが解決する方法かぁぁぁぁん?
<引用>
もう 1 つの方法は、ワーカー スレッドが処理するタスクごとに新しいユーザー定義の
メッセージを作成し、このメッセージを ::PostMessage 関数を使ってアプリケーション
のメイン ウィンドウに渡す方法です。この通信方法は、2 つの異なるアプリケーション
間の対話動作に似ています。ただし、2 つのスレッドが同じアドレス空間を共有する点
が異なります。
</引用>
ちょっと意味が判らんが、::PostMessage は重要だな。
ワーカースレッドからプライマリ(GUI)スレッドへは常に非同期であり、絶対に待たな
いし、ウィンドウに関する処理は一切禁止(PostMessageとかは可)。
というのは俺の経験で
GUIスレッドからワーカースレッドの待ちをしてデッドロックするからなんだ。
具体的にいうとワーカースレッドからSetWindowTextなどを実行していて、
ユーザが処理中止(一時停止じゃなくて取り止め)ボタン押すと、
処理中止がちゃんとワーカースレッドの後始末(ファイルクローズとか)終わるのを
確認するようにしちゃっていたりするとデッドロックする。
でも、沢山のデータをPostMessageじゃ渡せないんですけど。
ということで俺はワーカスレッドにデータを渡す目的でthisを渡しちゃってます。
単なる初期設定データを渡す目的なんでTLSとか関係ないんで問題ない。
二つの方法が提示されているが、これって併用するんじゃないのか?
PostMessageじゃワーカスレッドからウィンドウに非同期通信しか出来ねーよ。
長文は書いている俺がよくわからなくなるな(爆笑)。
> 別に危険でないです。
甘いな... (^^;;;
危険か危険じゃないかの議論は難しいな。
どの方法も誰がやってもバグが起きずに
マルチスレッドプログラミングが絶対できるわけじゃないから。
そういう俺はよくよく考えると最近CWndじゃないクラスを作って
AfxBeginThreadでthisを渡してメンバ関数をスレッドにしているな。
ということでCWndが原因の危険性はもともと低くかった(アハハハ)。
CWinThread 派生でもつくれるけど、やっぱ慣れみたいなものかな。
経験とか感覚的にそれで問題おきてないし。
というかBanさんと同じモデル的な感覚かな。
ある処理が非同期で動作する(並列処理)わけで、
このクラスがis CWinThreadというの感覚がない。
くりかえしになるけど CWinThread がだめだといっているわけじゃないよ。
それも充分ありな方法だ。慣れとか方針とか感覚とかの問題。
くだらんレスしてまで話に加わるがな。
書き直しが不十分な状態で送信してしまった(笑い)
そういうあなたは一言レスしてまで黙っていられない人ですね~
もう終わった話だと書きながらレスしたいほど。メクソハナクソ(笑い)
もともとは、AfxBeginThreadがとまる原因を追究しなくて
[危]と決め付けてプログラム変えて解決にして
いいのかよ~っていうことだったんだけど。
おまえら脱線しすぎだよ~(笑い)
たとえば、上司に直ったかって聞かれて
『調べてプログラム変えたら直りました』で済めばいいけど
理由聞かれて『分かりませんが動いてます』って答えたら
やばくないだろうかってことだよ。
てか、そもそもそれで直るのか疑問だ。
ということで脱線はしているものの、元質問には今でも注目しているのさ。
この議論はお遊びですよ。
今後もCWndオブジェクトを渡すことは(無条件で)絶対だめって
いうヤツが現われるし。
まるでCWndオブジェクト自体がTLSに置かれていて
別スレッドからはアクセスできないといっているような説明する人がいて面白いよ。
# そういう俺は最近CWndを渡さない方法を多用しているんだけどね。
それと、AfxEndThreadは終了するスレッドの内部から
呼び出してはいけないってヤツが現われるから、また楽しめるのさ。
おまえらだってレスするのが楽しいんだろ。俺に煽られた場合を除いてだけど
私のレスはこの手の議論に限らないよ。
繰り返しになるけど、
理由を知らないままとか、
それが事実か確かめないことに疑問を持つことにしたんだよ。
だからなぜ「危」なのか聞いてみた。
そのときは、こういう方向に進むとは思わなかった。
# ただ自分がまったく知らないことだと議論できないし
# 真実かどうか確認するのが難しいので、そのときはレスしないだろうな。
>MFC のウィンドウは、内部でTLS(スレッドローカルストレージ)を参照してたりして、
>むやみに this とか渡すと危険/意図しない動作する可能性があるわけですが、
>この認識はありますか。
もともと、通常「AfxBeginThread」で作成されるスレッドがワーカスレッドですから
「GUI」の処理を行うことの危険性は理解しているつもりです。
#「AfxBeginThread」ではワーカスレッド以外も作成できると思ったけど.......
使ってません。
僕はもともとスレッド内で「HWND」を使う処理はしません。
スレッド内でフラグを立てて、「CViewクラス」の中で行っています。
以前に、「HWND」が「NULL」になる例外を出して苦労しました。
どうしてもスレッド内で処理しないといけないときは、「CView」内に
スレッドを作って「CView」の「This」ポインターを使います。
イベント同期させれば、タイミングの問題は今のところないです。
それでも「描画」のみに留まり、ウインドウ操作は行いません。
「PostMessage」は大丈夫だったと思います。
話を折ってすいませんが、質問者の意図とは違う方向に
進んでしまっているようなので雑談掲示板なり新規スレ
立てたほうがいいと思うのですが。
# そうですね。脱線しちゃってごめんなさい。
# 認識があって使ってる分には、私も全否定する気はないのですが(スレッド間のthis).
..
話を戻すには、REE さんの
> 本題ですが、AfxBeginThreadで止まっていることをどう確認したのでしょうか?
や、RAPT さんの
> とありますが、実行環境は開発環境と同じWindows2000でしょうか。
> Windows9Xとかが絡んでくると、別の要因もありそうなので。
あたりでしょうか。
ちなみに、止まるか止まらないかが実行ファイルのMFCに依存してるとか、
そういうことはないですか。全部同じバージョンですか?
# スタックサイズが変わってたり、スレッド数が上限に達してたり、
# とかは現実的に関係なさそうですが。
疑問点は、
1. 「AfxBeginThread」の位置はあっているのでしょうか?
2. 同時に「sub_init()」が呼ばれる可能性はないでしょうか?
ですね。
排他制御していればいいですが......
脱線を煽ってしまうような形になってしまって申し訳なかったです。m(__)m
で、本題なんですが、「exeに依存して」止まる場合があるということから、
一番怪しいのは Ban さんが指摘されている MFC バージョンの不整合あたりでしょうかね。
レロリオさんの「大事なものを書き忘れてるとみた」が何を指しているかもちょっと気に
なりますが。AFX_MANAGE_STATEのこと?
ん~、何か、新しい情報提供ができてないですね(自分)
#CMainFrame とかの this 渡しについては、
#当人が CMainFrame 担当、サブスレッド担当は実力の知れない別の人、
#という想定のもとで this か HWND を渡せと言われたらどっちにするか、
#というのが当人にとっての危険度最終判断になるかと思います。
#僕は HWND 派です。どちらでも危険は免れないにせよ、HWND のが安全と思うから。
#(自分が親子両スレッドを担当し、終生見届けるならどっちも可なんですけどね)