2

私はC#で書かれたBHOを持っています。初期化はメイン スレッドの DocumentComplete イベント ハンドラで実行され、別のスレッドを開始し、そのスレッドで IMarkupServices を使用したいのですが、次のエラーが発生します。

System.InvalidCastException: タイプ 'mshtml.HTMLDocumentClass' の COM オブジェクトをインターフェイス タイプ 'mshtml.IMarkupServices' にキャストできません。IID '{3050F4A0-98B5-11CF-BB82-00AA00BDCE0B}' を持つインターフェイスの COM コンポーネントでの QueryInterface 呼び出しが次のエラーのために失敗したため、この操作は失敗しました: No such interface supported (HRESULT からの例外: 0x80004002 (E_NOINTERFACE)) .

初期化の方法は次のとおりです。

void ieInstance_DocumentComplete(object pDisp, ref object URL)
{
    InternetExplorer explorer = pDisp as InternetExplorer;
    _ieHtmlDocument2 = (IHTMLDocument2)explorer.Document;
    _markupServices = (IMarkupServices)_ieHtmlDocument2;
    _markupServices.CreateMarkupPointer(out _markupPointerBeginGlob);  // No exception here
    _workerThread = new Thread(WorkerThread);
    _workerThread.IsBackground = true;
    _workerThread.SetApartmentState(Thread.CurrentThread.GetApartmentState());
    _workerThread.Start();
}

スレッド プロシージャは次のとおりです。

void WorkerThread()
{
    _markupServices.CreateMarkupPointer(out _markupPointerBeginGlob);  // Exception here!
}

EDIT: C++では、必要なものを達成するために次の関数を呼び出す必要があるようです:

CoMarshalInterThreadInterfaceInStream
CoGetInterfaceAndReleaseStream

EDIT2:

CoMarshalInterThreadInterfaceInStream / CoGetInterfaceAndReleaseStream を明示的に呼び出そうとしましたが、まだ結果がありません (マークアップ サービスを使用しようとすると、同じ例外がスローされます)

4

1 に答える 1

1

ワーカー スレッドに渡すIMarkupServicesには、最初にインターフェイスを実装して使用できるようにする必要があります。また、マーシャリングも可能にする必要があります。後者では運が悪いようです。インターフェイスには、タイプ ライブラリまたはカスタム プロキシ/スタブ クラスへの参照がありません。また、自動プロキシ/スタブ ペアを提供することもできません。したがって、アパートの境界を越えることはできません。

アップデート。ここでの要点は、インターフェイスを別のスレッドに渡すことができる場合、オブジェクト自体が基になるマーシャリング モード (アパートメント タイプ、オブジェクトの実装の可用性に依存IMarshal)、バックグラウンド スレッドから直接オブジェクトにアクセスできるかどうか、またはこのアクセスを示すことです。オリジナルスレに連載予定です。後者の場合、ワーカー スレッドへのマーシャリングは UI スレッドの応答性を維持する可能性がありますが、マーシャリング コストが増加するため、全体の処理が遅くなる可能性があります。あなたの場合、最初にマーシャリングすることはできません。

基本的に、元のスレッドで作業するオプションのみが残されています。ネイティブ ドメインでは、COM ガイドラインに違反して生のポインタをバックグラウンド スレッドに渡し、そこから操作することもできます。これは動作が保証されているわけではなく、お勧めしませんが、オブジェクト自体によってはうまくいく場合もあります。マネージ コードでは、このトリックはあまり推奨されません (可能であれば)。

于 2013-01-17T22:30:50.960 に答える