ActiveXEXEからのイベントの受信について

解決


との  2005-05-10 14:26:08  No: 89739  IP: [192.*.*.*]

VB6.0でActiveXEXEでイベントを発生させ、標準EXE側でイベント
を受信しています。
通常は、標準EXE側でイベントの受信が出来るのですが、まれに受信が
できないことがあります。
ActiveXEXEでイベントを発生させていることは確認済みです。
イベントが受信できない原因、または対処方法を宜しくお願いします。

編集 削除
K.J.K.  2005-05-10 20:59:06  No: 89740  IP: [192.*.*.*]

受信側のメッセージループを阻害するようなコードを入れて
いませんか?もしくは、そういう行動(例えばタイトル上
でマウス右ボタンを押しっ放し、とか)を行っているとか。

もっとも、これらなら、App.OleServerBusy???プロパティ
やApp.OleRequestPending???プロパティをいろいろ使えば、
それなりの検出・対処ができるでしょう。

提示された情報だけでは、これ以上のことは言えません。

編集 削除
との  2005-05-11 09:59:32  No: 89741  IP: [192.*.*.*]

K.J.K.さん
回答ありがとうございます。

御指摘の通り、受信側ではEnumWindowsを使用し、コールバック
関数(ActiveXEXEの存在チェック関数)を呼び出しています。
それが「メッセージループを阻害するようなコード」に該当して
いるのかもしれません。
コールバック関数中に「DoEvents」をいれておくことで対応でき
るかもしれませんが、実は「イベントが受信できない」ときの条
件が明確になっていないため、対応できているかの確認ができな
いの状態です。。。
App.OleServerBusy???プロパティ等を使用して調査してみます。

編集 削除
K.J.K.  2005-05-11 13:14:03  No: 89742  IP: [192.*.*.*]

どうも無駄で冗長な構造になっているように思えます。
そもそも、存在チェックをなぜするのでしょうか?
何か変化があったらサーバ側から通知する、とすべきでは。

で、受信側では極力メッセージを受け取る機会を用意しておかな
ければなりません。時間のかかる処理がある場合は、DoEventsを
使うとかする以前に、その処理を細かく切り分けて、メッセージ
ループそのものをブロックしないようにすべきでしょう。

ActiveX EXEでのイベントの通知は、COMを介してのメッセージの
やり取りですから、必ずしも成功するとは限りません。但しDDEに
比べれば、遥かに信頼できます。

一般的には、↑に合わせて、
1,DDEよりは頻繁に連絡をとる。
2,ActiveX DLLほどは頻繁には連絡をとらない。
ように組み立てます。ActiveX DLL並に頻繁にイベント通知を
受け取る必要がある場合は、プロジェクトの構造そのものを
見直すべきです。

編集 削除
との  2005-05-11 18:11:58  No: 89743  IP: [192.*.*.*]

> そもそも、存在チェックをなぜするのでしょうか?
これは、タスクマネージャでActiveX EXEを落とす意地悪テスト
対応のためで、実際には必要の無い処理です。
この処理は外すようにします。

> ActiveX EXEでのイベントの通知は、COMを介してのメッセージの
やり取りですから、必ずしも成功するとは限りません。
上記の件ですが、どのようなところからの情報でしょうか。
不勉強ですみません。
マイクロソフトがそのようなことを言うとは思えなかったので。

もともとActiveX EXEを使う理由は、データの送受信中に画面をブリ
ンク表示させる(VBで非同期処理をおこなう)ためです。
COM自体の信頼性が低いということであれば、ActiveX EXEでおこ
なっている処理を標準EXE側に組み込む方向で考えようと思います。

編集 削除
K.J.K.  2005-05-11 21:49:03  No: 89744  IP: [192.*.*.*]

とりあえず、最初に提示したApp.OLERequestPendingTimeoutプロパティや
App.OLEServerBusyRaiseErrorプロパティなどについて調べましたか?
これらは、メッセージを介してのメソッドやイベントの通知に失敗する
ことがありえるからこそ、それに対応するために存在しているプロパティ
ですよ。

MSDNで、
Component Object Model (general)
 COM SDK Documentation
  COM
   COM Fundamentals
    Guide
     COM Clients and Servers
      Inter-Object Communication
辺りを読んでみるとか。他にIMessageFilterの説明などもヒントに
なるでしょう。

で、
データの送受信を、UIを持たないActiveX EXEで、
UIは標準EXEで、
という組み方そのものは、さほど問題がないと思われます。
プロセス間のやりとりの量・頻度を、それ相応にしておけば
大抵は大丈夫ですよね。

こういうときは、あまりUIにこらない、妥協する、ということ
も重要です。その画面の点滅というのはかなり気になる処理
ですが、そこでメッセージループに入るのを妨げている、と
いうことはありませんか?

別にActiveX EXEだけに限りませんが、非同期(スレッド・
プロセス)間通信にはゆとり・余裕が必要です。それなのに、
同スレッド内でのオブジェクト間の通信と全く同じ手法で
行っているように見受けられます。

編集 削除
との  2005-05-12 18:21:48  No: 89745  IP: [192.*.*.*]

K.J.K.さん
色々と助言を頂き、ありがとうございます。

> とりあえず、最初に提示したApp.OLERequestPendingTimeoutプロパティや
> App.OLEServerBusyRaiseErrorプロパティなどについて調べましたか?
> これらは、メッセージを介してのメソッドやイベントの通知に失敗する
> ことがありえるからこそ、それに対応するために存在しているプロパティ
> ですよ。
ヘルプを確認しましたが、「それに対応するために存在しているプロパティ」
と読み取ることができていませんでした。。。
また、提示されましたMSDNのCOMの部分ですが、翻訳サイトで和訳しつつで
苦戦しています。

> その画面の点滅というのはかなり気になる処理
> ですが、そこでメッセージループに入るのを妨げている、と
> いうことはありませんか?
確かに、ActiveX EXEからのイベントを受信待ちの間、forループに入って待機
しています。
この部分をforループではなく、ある程度の間隔でタイマー監視するように
修正したいと思うのですが、修正規模が大きくなるために躊躇しています。

今後の方針としては、以下の2つで考えています。
  ①ActiveX EXEの存在チェックを外す
  ②ActiveX EXEをActiveX DLLへ変更する、まはた標準EXE内へ組み込む

K.J.K.さんのおかげで、いくつかの原因が見えてきました。
また、何かありましたらコメントを頂ければと思います。

編集 削除
K.J.K.  2005-05-13 10:20:03  No: 89746  IP: [192.*.*.*]

Forループで待機(Sleepもしくは空回し)というのは、
Windowsアプリとしてはかなり問題のあるコードです。
コンソールアプリではないのですから。

Windowを持っているスレッドでは、待機にはメッセージ
ループを止めないMsgWaitForMultipleObjects(Ex)を
用いてください。SleepやWaitForSingleObject(Ex)、
WaitForMultipleObjects(Ex)では、明示的に処理しない
限り、キューにたまったメッセージを処理する機会が
与えられません。

編集 削除
tono  2005-05-16 11:09:43  No: 89747  IP: [192.*.*.*]

K.J.K.さん

何度もアドバイスを頂きありがとございます。

本件ですが、以下の理由により、一旦解決とさせて頂きます。
  ①修正すべき項目がある程度判明した
  ②再現条件が明確になっていない
上記②については、当方にて確認すべき内容であり、その上で修正作業
が必要と考えています。
また質問させて頂くこともあるかと思いますが、宜しくお願い致します。

編集 削除
との  2005-05-16 11:10:58  No: 89748  IP: [192.*.*.*]

解決マークを付け忘れました。。。

編集 削除