- PR -

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

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

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



かもしれませんが、元もとの OCX → DLL 呼び出しがシリアライズされていれば、ここが問題になることは無いですよね?

DLL 経由で OCX が結果を受け取るまで、次の呼び出しが行われることは無いはずなので。

(サービスが複数同時リクエストをさばけないつくりなのは問題、サービス側のメソッド「こそ」なんらかの方法で複数同時呼び出しから保護されるべき、って点はおいておくとして)

そうすると問題の直接的な原因は、VB のというか、.NET の CCW が OCX に対する呼び出しを外部に対して非同期(っぽく)投げてしまっているからじゃないかと思うんですが、違うかな?
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-06-29 07:33
引用:

上記のようなコードでも結果は同じで、排他が効きませんでした。
(もちろんMTAでも同様に効きませんでした)
そもそもVB.NETのAP(EXE)のスレッドモデルをSTAに設定というのはやり方が間違っているのでしょうか?



ワーカースレッドへの設定はあっていますが、そもそも OCX のインスタンスを生成しているスレッド(=大抵はプライマリスレッド)が STA になっているかも確認してみてください。

Main メソッドの属性か、リンカオプション?でも設定できるようです。
Atata!!
常連さん
会議室デビュー日: 2007/05/22
投稿数: 20
投稿日時: 2007-06-29 15:00
引用:

DLL 経由で OCX が結果を受け取るまで、次の呼び出しが行われることは無いはずなので。


この呼び出しが行われるのが今回の問題の複雑さではないかと私は思います。

仕事から帰った後で、私が検証のため作成したサンプルをアップしたいと思います。
まぁ、ちょっと試していただければ幸いです。


引用:

そうすると問題の直接的な原因は、VB のというか、.NET の CCW が OCX に対する呼び出しを外部に対して非同期(っぽく)投げてしまっているからじゃないかと思うんですが、違うかな?


結論はそうだと私も思います。
ですので、Control.Invoke による明示的な同期化が解決策としては最善なのではないかと。
もしくはOCXを使わずに直接DLLを呼び出すとか・・・。
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-06-29 16:12
引用:

引用:

DLL 経由で OCX が結果を受け取るまで、次の呼び出しが行われることは無いはずなので。


この呼び出しが行われるのが今回の問題の複雑さではないかと私は思います。



あぁ、そうですよね。

なんとなく、DLL→サービスの呼び出し機構に起因する問題だと指摘しているような印象を受けたので。

引用:

ですので、Control.Invoke による明示的な同期化が解決策としては最善なのではないかと。



コストはそれがイチバン安いですね。
性能も従来とそれほど変わらないだろうし。

でも、本来修正するべきはサービスの方のような。
呼び出し側で呼び出しをシリアライズして保護してやら無いといかんようなオブジェクトなんて…

引用:

もしくはOCXを使わずに直接DLLを呼び出すとか・・・。



アプリから直接サービスを呼んじゃ駄目なんですかね?

# 勢いで CCW って書いてましたが、今回は .NET→OCX なので RCW (Runtime Callable Wrapper) ですね。


[ メッセージ編集済み 編集者: 渋木宏明(ひどり) 編集日時 2007-06-29 16:14 ]
Atata!!
常連さん
会議室デビュー日: 2007/05/22
投稿数: 20
投稿日時: 2007-06-30 01:38
とりあえず、私のサイトに検証に使用したソースをアップしました。
興味のある方は動かしてみて頂けると良いかと思います。
www5.plala.or.jp/atata/download/rpcsample.lzh
ビルドは Service => DLL => OCX => APP(VB.NET) の順番で行う必要があります。
ビルド完了後、DLLをOCXのDebugフォルダにコピーする必要がありますが、
ビルド後のイベントを組んで無いので、手動でのコピーをお願いします。
なお、実行時の経過はOutputDebugStringで出力しているので、これを監視するツールを準備する必要があります。


引用:

でも、本来修正するべきはサービスの方のような。
呼び出し側で呼び出しをシリアライズして保護してやら無いといかんようなオブジェクトなんて…
...
アプリから直接サービスを呼んじゃ駄目なんですかね?


私もそうあって然るべきと考えていますが、これ以上はスレ主の状況次第ですので私からは何とも言い様が無いです。


少なくとも、STAを経由したCOMの呼び出しは可能な限り避けるように設計しなければならないと私は考えています。
# 設計段階を過ぎているならば、ほとんどの対策は焼け石に水と思っているんですが・・・。
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-06-30 11:03
引用:

とりあえず、私のサイトに検証に使用したソースをアップしました。



@IT のプロファイルにはサイトの URL を登録してないんですね (^^;
ちゃーはん
会議室デビュー日: 2007/06/25
投稿数: 13
投稿日時: 2007-07-02 09:00
渋木さん、Atata!!さん、ありがとうございます。

引用:

でも、本来修正するべきはサービスの方のような。
呼び出し側で呼び出しをシリアライズして保護してやら無いといかんようなオブジェクトなんて…
...
アプリから直接サービスを呼んじゃ駄目なんですかね?


色々と制約があって直接サービスを呼ぶ等々の影響が大きめな変更は認められない状況なんです。
なんとか小手先の手法で対応できればと思っていたのですが、やはり難しいみたいですね・・・
今の状況ではControl.Invokeで使ってもらうということが一番確実、安全なのかなと思っています。

#他ではこのような問題って起こってないんですかね?
#特に昔のものを単純に引きずっていってるようなものだと同じような問題にぶつかりそうに思うんですが
#あまりこういった話題を見かけないので、やっぱりちゃんとそこらへんを見越した設計されてるのかなぁ・・・
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-07-02 12:11
引用:

#特に昔のものを単純に引きずっていってるようなものだと同じような問題にぶつかりそうに思うんですが



ここまで多段で、最上流でシリアライズしなくちゃならないヤツってのは珍しいんじゃないですかね。

僕なら「全とっかえ」が引き受ける条件です

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