- PR -

アンマネージドとマネージドのスレッド対応

投稿者投稿内容
ちゃーはん
会議室デビュー日: 2007/06/25
投稿数: 13
投稿日時: 2007-06-28 14:11
渋木さん、Atata!!さん、ありがとうございます。

分からないなりに自分でも色々と試してみたりしましたが、
やはりなちゃさんやAtata!!さんの言われることが原因のようです。

しかし相変わらず解決策を見出せていません。
引用:

典型的なCOMスレッド地獄と言えなくもないですなぁ。


地獄で足掻くしかないでしょうか・・・

しかもこれってマネージド、アンマネージドや.NETとかがメインの問題じゃないですよね。
自分の勘違いとは言え、ここにスレ立てちゃって申し訳ありませんでした。
Atata!!
常連さん
会議室デビュー日: 2007/05/22
投稿数: 20
投稿日時: 2007-06-28 16:20
解決策はご自身で書き込まれている下記の方法で問題無いのではないでしょうか?
引用:

ただVB.NETのAPからでもOCXオブジェクトのInvokeを使いデリゲードで実行するとマルチスレッドでもちゃんと排他が効きます。(これも見よう見真似でやったんもんで自分もなぜうまくいくのか理解できていません、お恥ずかしい・・・)


この問題が私の推論通りであればCOMの機能を使用して解決することも出来ますが、
経験上、新たな問題を発生させることの方が多いです。


引用:

しかもこれってマネージド、アンマネージドや.NETとかがメインの問題じゃないですよね。
自分の勘違いとは言え、ここにスレ立てちゃって申し訳ありませんでした。



私はVB.NETでマルチスレッドプログラミングの敷居が下がったため、
この類の問題は以前より増えているように感じます。(特にOCX関連)
で、COM相互運用の問題として、ここに立てるのも悪くない気がします。
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-06-28 18:41

RPCがメッセージまわしちゃってるということですか。

ややこしいですね。

渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-06-28 18:50
引用:

RPCがメッセージまわしちゃってるということですか。



純粋な RPC はメッセージポンプは回さないです。
この場合はたぶん、LPC です。

サービスってことは別プロセスなんだから、そこで幾らポンプを回しても、呼び出し元には影響ないはずなんだけどなぁ。
Atata!!
常連さん
会議室デビュー日: 2007/05/22
投稿数: 20
投稿日時: 2007-06-28 20:30
引用:

純粋な RPC はメッセージポンプは回さないです。
この場合はたぶん、LPC です。

サービスってことは別プロセスなんだから、そこで幾らポンプを回しても、呼び出し元には影響ないはずなんだけどなぁ。



便宜上RPCと呼んでますが、この場合間違いなくLPCです。

サービス側のメソッドを呼び出して
メソッドの呼び出し元に復帰する直前(スレッドコンテキストはSTAスレッド上)に、
RPCの実行キューから溜まった処理を取り出して実行していると思われます。
STAスレッドのメッセージポンプは動かないはずです。
この時キューから取り出した情報が、サービス側のメソッドを呼び出した結果であるならば、
そのまま呼び出し元に復帰すると考えられます。
Atata!!
常連さん
会議室デビュー日: 2007/05/22
投稿数: 20
投稿日時: 2007-06-28 20:44
なんと言うか、実行キューとか再入とか書いたので誤解を与えている気がします。

更に言うと私が呼んでいるRPCの実行キューは、
呼び出し順番がよく分からないことが多いので、
キュー構造になっているかどうかも正直分かりません。
# まぁ、大体FIFOで動作してるように見えるんですが。


# このスレッドが面白いので、今日はあんまり仕事してないなぁ・・・。
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-06-29 00:53
んーっと
どのスレッドがどのメソッドを呼んでどのキューを処理しているのか、
私にはよく理解できませんでした。

AP(MT) <-> OCX(ST) <-> DLL <-(LPC)-> ATL

MultiThreadのAPからSingleThreadなOCX呼ぶところでキューが入るのはいいとして、
DLLからATL呼ぶときのLPCで
OCXのメッセージポンプに戻らないと今回の様にはなりませんよね。

>実際には、RPCランタイムはSTAスレッドの実行キューに先に溜まっている処理を実行する。

>STAスレッドのメッセージポンプは動かないはずです。

実行キューを処理するのにメッセージポンプが動いてないとは
どーゆーことでしょう?



そういや「reentrant」という言葉なんですが、wikipediaによると

>A computer program or routine is described as reentrant if it can be safely called recursively or from multiple processes.
>リエントラント(Reentrant、再入可能)とは、プログラムやサブルーチンが、静的な内部状態をもたないので、再帰的にも、複数のスレッドからも、データを壊すおそれなく呼び出せる場合をいう。

とあり、すでに「可能」の意味があります。
英語で〜antは可能の意味を持ちますので。

ですので、「reentrantする」は変です。
「reentrantである」ならばそのままですが。
どうしても「再入する」といいたいときは「reentrance」ですね。

the reentrance to the RPC (RPCへの再入
the problem of reentrances (再入している問題
reentrant functions (再入可能な関数


あ、もうひとつ。

># 実際のところマルチスレッドなので再入とは言えないか。

マルチスレッドでも再入です。
自分が抜けてない内に、他のスレッドか自分自身入れるのであれば再入可能。
自分が抜けてない内に、他のスレッドが入れるのであればスレッドセーフ。
Atata!!
常連さん
会議室デビュー日: 2007/05/22
投稿数: 20
投稿日時: 2007-06-29 04:34
引用:

DLLからATL呼ぶときのLPCで
OCXのメッセージポンプに戻らないと今回の様にはなりませんよね。



私が述べているSTAスレッドの実行キューとはWindowsのメッセージキューではありません。
(実際のところ実装がどうなっているかまでは分かりませんが)
RPCランタイムが管理するデータの論理的な構造について述べているつもりです。
ですので、このキューはメッセージポンプとは関係がありません。

DLLからサービスのインターフェースプロキシを呼び出した際、
プロキシの内部で上記キューのデータが処理されます。
処理された結果、新しく別のメソッド呼び出しが開始されるわけです。
プロキシ内部で処理されるタイミングはLPC呼び出しの後であることは確かです。


あと、私の記述にも明らかな間違いがありました。
よくよく調べてみるとメソッドの復帰情報は実行キューには詰まれていないようです。
LPC(RPCも同様)呼び出しから復帰した時には既に復帰情報は得られています。
InsideDCOMのプロキシ/スタブの解説と今回の現象を再現するコードから確認しました。
失礼しました。


引用:

そういや「re-entrant」という言葉なんですが、wikipediaによると...


私の「re-entrant」の解釈はかなり間違ってますね。
今回のような話題を述べる時には特に気をつけたいと思います。

スキルアップ/キャリアアップ(JOB@IT)