- - PR -
アンマネージドとマネージドのスレッド対応
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2007-06-26 10:25
VCとVB(いずれれもVS6と.NET版)を使用している者です。
VC6(アンマネージド)で作成したDLL、ATLサービスEXEがあり、それをVB.NET(マネージド)で作成したAPでリンクしています。 AP(VB.NET マネージド) ⇔ DLL(VC6 アンマネージド) ⇔ ATLサービスEXE(VC6 アンマネージド) このDLLのあるメソッドでATLサービスEXE側の@データ生成、Aデータ転送、Bデータクリアというを三つのメソッドをコールして完結するものがあります。 このATLサービスEXEのメソッドはあるリソースをアクセスするため、マルチでコールされることを考慮して、DLLのメソッド内でミューテックスを使って排他を行っています。 @データ生成の前にロックし、Bデータクリア後にアンロックするという形です。 ところがマネージドとアンマネージドのスレッドが1対1ではなく、n対1の対応になることがあるようです。(これはまだよく調べ切れていないので自分も理解できていませんが・・・) 実際にVB.NET(マネージド)からこのDLLをメソッドをマルチスレッドでコールした場合に 、もちろんVB側ではスレッドはマルチで動作するですが、DLL側では一つのスレッドしか動作していないようです。(DLL側は常にスレッドIDが同じ) 同一スレッド上ではミューテックスやクリティカルセクション、セマフォなどの排他・同期は効かずに、そのままDLLからATLサービスEXE側のメソッドが連続して呼ばれてしまいます。 このため前の処理が終わらないうちに次の処理が動き、後の処理中に前の処理のデータクリアが呼ばれてしまい、後の処理の途中でデータが空っぽになるとう障害で困っています。 AP側もアンマネージドならば問題なく動作します。 ちなみにAP側からマネージドコードでDLLをコールすることの変更や、DLLやATLサービスEXE(修正は可能ですが)をアンマネージドからマネージドへの変更はいずれも仕様上、できないことになっています。 このことに関して対応方法をご存知の方がいらっしゃれば教えていただけないでしょうか? またこれらについて解説しているようなサイトや書籍があれば、あわせて教えて頂ければと思います。 よろしくお願いします。 | ||||||||
|
投稿日時: 2007-06-26 10:32
System.Threading.Thread.BeginThreadAffinity メソッド
| ||||||||
|
投稿日時: 2007-06-26 10:46
なんとなく原因がような違う気もする…
dllはどうやって呼び出してますか? | ||||||||
|
投稿日時: 2007-06-26 10:59
yaさん、ありがとうございます。
BeginThreadAffinity、恥ずかしながら知りませんでした。 ただこれはNET Framework version 2.0で追加されたものとの記述があり、 VB.NET版APについては説明不足で申し訳なかったのですが、VC2002〜VC2005まで対応する必要があり、その関係でAP作成環境が必ずしもNET Framework version 2.0がインストールされているとは限らないもので、その観点からすると難しいのかなと思いました。 (自分の環境も社内ルールで制約があり、1.0しかインストールできていませんでした・・・悲) また何かありましたら、是非教えて頂けますよう宜しくお願いたします。 | ||||||||
|
投稿日時: 2007-06-26 11:10
なちゃさん、お返事ありがとうございます。
引用: -------------------------------------------------------------------------------- なんとなく原因がような違う気もする… dllはどうやって呼び出してますか? -------------------------------------------------------------------------------- すません、完全に一つ書き忘れていました。 VB.NETとAPとDLLとの間にはラッパーとしてOCXをかませています。 したがって実際は AP ⇔ OCX ⇔ DLL ⇔ ATL というものになります。 更に申し訳ないのですがOCX、DLL、ATLはVC6で作成されたものですが、これをVC2002にコンバート後ビルドしたものを使っています。(コード的には全く変更していません) 説明不足で、本当にすいませんでした。 宜しくお願いします。 | ||||||||
|
投稿日時: 2007-06-26 12:06
そうです。
マネージ/アンマネージ云々に関係なく、その動きが変です。 ミューテックス、セマフォはプロセスグローバルで有効な同期オブジェクトなので、スレッドが1対1でないことの影響は受けません。 また、クリティカルセクションはプロセス内だけで有効な同期オブジェクトですが、同一プロセス内であるなら同一プロセス内のすべてのスレッドと同期をとることができます。 ということで、今のところ提示された情報からは、マネージスレッドがアンマネージスレッドと1対1対応しないことが問題の原因であるとする根拠は見つかりません。 | ||||||||
|
投稿日時: 2007-06-26 13:30
渋木さん、お返事ありがとうございます。
引用:--------------------------------------------------------------------------- マネージ/アンマネージ云々に関係なく、その動きが変です。 ミューテックス、セマフォはプロセスグローバルで有効な同期オブジェクトなので、スレッドが1対1でないことの影響は受けません。 また、クリティカルセクションはプロセス内だけで有効な同期オブジェクトですが、同一プロセス内であるなら同一プロセス内のすべてのスレッドと同期をとることができます。 ということで、今のところ提示された情報からは、マネージスレッドがアンマネージスレッドと1対1対応しないことが問題の原因であるとする根拠は見つかりません。 -------------------------------------------------------------------------------- 今のところやはり原因は不明です。 どの方法をとってみても、WaitForSingleObeject等の待ちの処理も表面上(戻り値等)は正常であり、一切エラーがなく、ただなぜか待たずにそのままするっと抜けるという状態です。 ただVB.NETのAPからでもOCXオブジェクトのInvokeを使いデリゲードで実行するとマルチスレッドでもちゃんと排他が効きます。(これも見よう見真似でやったんもんで自分もなぜうまくいくのか理解できていません、お恥ずかしい・・・) またアンマネージドAP(VC)をマネージド拡張に変更し、その中のマネージドクラスでDLLのメソッドをマルチでコールしても排他が効きます。 やはり言われる通りスレッドの問題ではないのでしょうか? ただDLL側にバグ的な問題があるとも思えず、手詰まりの状態です。 自分がVB.NET(というかマネージドを)を分かっていないもので、何か設定や呼び方に問題があるのかとも考えています。 | ||||||||
|
投稿日時: 2007-06-26 14:25
Managed なEXEのスレッドモデルとOCXのスレッドモデルは一致していますか? スレッドモデルが一致していないと、スレッド処理はグダグダになりますよ。 排他制御や同期処理というあたりはとくに... OCX側は何もしていなければ、Apartment(STAと同じ)だと思いますので、Managed のスレッドモデルもSTAになっていないと上手くいかないとおもいます。 そのあたりもあらってみてください。 _________________ // とっちゃん(高萩 俊行)@わんくま同盟 // とっちゃん’Blog // MS-MVP for Developer Tools - Visual C++ // WindowsInstallerの話題はhttp://www.freeml.com/msiまで |