ActiveXでのイベント生成について – プログラミング – Home

ActiveXでのイベント生成について
 
通知
すべてクリア

[解決済] ActiveXでのイベント生成について


えちぜん
 えちぜん
(@えちぜん)
ゲスト
結合: 14年前
投稿: 4
Topic starter  

えちぜんといいます。

開発環境
 VisualStudio2005 Visual C++

ActiveXコントロールをATLにて作成しています。
MFCは使用していません。

コントロール内のメソッドから_beginthreadを用いてあるデバイスを監視し、終了した
時点でFire_AnsMessageのメソッドを呼ぶようにしました。

ActiveXコントロールテストコンテナを用いて動作を確認したところ、ログウィンドウに
イベント発生時のメッセージが出力されていることを確認しました。

しかし、これをブラウザ(IE8)で動かすとイベントが発生しません。
スレッド内でFire_AnsMessageを呼び出さず、コントロール内のメソッドで呼び出せばブ
ラウザでも動作することを確認しましたので、スレッドが絡んだ問題だろうということ
はわかったのですが、どのような処理が必要なのでしょうか。

---- ソース -----

STDMETHODIMP CFingerCtrl::GetData(LONG no)
{
CFingerParam* param = new CFingerParam( this, no);
::_beginthread( AnsGetData, 0, param);
}

// スタティックメソッド
void CFingerCtrl::AnsGetData( void* obj)
{
CFingerParam* ctrl = (CFingerParam*)obj;
CFingerCtrl* p = ctrl->GetCtrl();
long no = ctrl->GetNo();
delete obj;
while( true)
{
if( !p->device->GetData())
::Sleep(1000);
else
break;
}
p->Fire_AnsMessage(no, L完了しました。);
}


引用未解決
トピックタグ
subaru
 subaru
(@subaru)
ゲスト
結合: 19年前
投稿: 381
 

スレッド側からイベントを発行しているので
STAスレッドでは補足できないということなのかもしれません。
メインスレッドからイベントを発行するようにしてみてはいかがでしょうか。


返信引用
えちぜん
 えちぜん
(@えちぜん)
ゲスト
結合: 14年前
投稿: 4
Topic starter  

> subaruさん

メインスレッドからイベントを発行できればそれがいいのですが、
デバイスへの入力待ちなどがありますのでスレッド起こしすしかないかと考えていま
す。
メインスレッド側へ何らかのメッセージを送ることも考えたのですが、ウィンドウハン
ドルはNULL(m_hWndがNULLでした)になってるようで送り方もわからない状態です。

デバッグしていると、以下の部分までは動作していることを確認しました。
致命的なエラーらしいのですが・・・

HRESULT Fire_AnsMessage( LONG no, BSTR data)
{
    ・

    ・
ここでE_UNEXPECTED
 -→ hr = pConnection->Invoke(1, IID_NULL,
LOCALE_USER_DEFAULT,DISPATCH_METHOD,
&params, &varResult, NULL, NULL);
}
}
return hr;
}


返信引用
ロマ
 ロマ
(@ロマ)
ゲスト
結合: 18年前
投稿: 170
 

スレッド毎にCoInitializeして、
STAだったらインターフェースの生ポインタではなく、
プロキシを渡す必要があります。
それがいやなら、COMを所有しているスレッドに処理を依頼する手もありそうです。


返信引用
えちぜん
 えちぜん
(@えちぜん)
ゲスト
結合: 14年前
投稿: 4
Topic starter  

IEではActiveXコントロールをSTAで動作させるため、そのままではスレッド間でやり取
りができないという認識でいいのでしょうか。(テストコンテナではMTAで動作させてい
る?)

> ロマさん
プロキシとは、接続ポイントで生成されたCProxy_***というクラスのことでしょうか。
CFingerCtrlの派生元にこのクラスがあるみたいなので、上記コードでも大丈夫のような
気がしますが、私なにか勘違いしてるでしょうか。

また、調べたところマーシャリングが必要らしいということはわかったのですが、やり
方はまだよくわかってません。


返信引用
えちぜん
 えちぜん
(@えちぜん)
ゲスト
結合: 14年前
投稿: 4
Topic starter  

インターフェイスをマーシャルし子スレッドに渡し、アンマーシャル後イベントを発行
することでうまく動作しました。

subaruさん、ロマさん、ありがとうございました。

-- 親スレッド側 --
接続ポイント?(IDispatch*)をマーシャルしIStream*の配列にし子スレッドに渡しまし
た。

IStream* stream = NULL;
HRESULT hr = S_OK;
std::vector<IStream*> streames;

CProxy_IFingerCtrlEvents<CFingerCtrl>* pT =
static_cast<CProxy_IFingerCtrlEvents<CFingerCtrl>*>(this);
int nConnectionIndex;
int nConnections = pT->m_vec.GetSize();
for (nConnectionIndex = 0; nConnectionIndex < nConnections;
nConnectionIndex++) {
Lock();
CComPtr<IUnknown> sp = pT->m_vec.GetAt(nConnectionIndex);
Unlock();
IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
if (pDispatch != NULL) {
stream = NULL;
hr = CoMarshalInterThreadInterfaceInStream(IID_IDispatch, pDispatch,
(IStream**) &stream);
streames.push_back( stream);
}
}

-- 子スレッド側 --
IStream*の配列をパラメータとして渡し、IDispatch*にアンマーシャルしInvokeメソッ
ドを実行しました。
std::vector< IStream*> streams;
std::vector< IStream*>::iterator it;
std::vector< IDispatch*> dispatches;
std::vector< IDispatch*>::iterator itdispatch;

 ・
for ( it = streams.begin(); it != streams.end(); ++it){
IDispatch* dispatch = 0;
hr = CoGetInterfaceAndReleaseStream( *it, IID_IDispatch, (void**) &dispatch);
dispatches.push_back( dispatch);
}
 ・
 ・
hr = (*itdispatch)->Invoke(3, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD,
&params, &varResult, NULL, NULL);


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました