C# IE BHO:同じスレッドを維持しながら非同期で動作しますか?
-
13-09-2019 - |
質問
C# で開発中の IE BHO があります。ユーザーが何らかの操作を行い、サーバーに接続してデータをダウンロードし、その結果で現在ロードされている Web ページの DOM を変更するのを待つことになっています。
COM の区分化とスレッド化のルールに関連して、一見克服できない問題がいくつか発生しています。つまり、現在のスレッドの外では IE DOMDocument にアクセスできないようで、ロックせずに何かを非同期で実行する方法が思いつきません。完了するまで IE を起動します。
私の最初の試みでは、バックグラウンドのサーバー通信がイベント駆動型の方法で動作するようにしました。私のプログラムは、mshtml イベント (BeforeNaviagate2 や DocumentComplete など) 内から通信を開始し、作業の終了時にサーバー通信オブジェクトによって起動される別のイベント ハンドラー内から結果をポストします。
この手法は、私がまとめた簡単なシミュレーター (WebBrowser コントロールを備えた単純なアプリ) ではうまく機能しましたが、IE では別のスレッドを通じてページ DOM を変更しようとしたため、COM 例外がスローされます。
そこで、すべてを同じ関数内に保持し、サーバー通信オブジェクトが while ループで処理するのを次のようにコードで待機させてみました。
int waited = 0;
while (!OurServerCommRequest.ready) {
System.Threading.Thread.Sleep(1);
Application.DoEvents();
waited++;
if (waited > constants.TIMEOUT_OURSERVER_REQUEST) {
log.wL("Timed out");
}
}
このアプローチの問題は、コードが元のスレッドに残っている間、コードが起動された IE プロセスと同期して実行されることです (IE8 では、Google Chrome のように、タブごとに 1 つのプロセスであるようです) ...したがって、サーバー通信が完了するまで IE インターフェイスがロックアップされます。
当初、URL が (NavigationComplete2 イベント経由で) 利用可能になったらすぐに処理を開始したいと思っていましたが、ユーザーのページが読み込まれる前にサーバー通信が終了すると、<body> タグが利用可能になるのを待機していると、IE もロックされてしまうことがわかりました。コードが HTML 本文を待機している間、無限ループに陥り、前述のループによりページ自体の更新が妨げられます。
これらすべてを実際のユーザーのページの JavaScript に移動することを考えましたが、そうすることで XSS のセキュリティ問題と格闘するワームの缶を開けているようです。
それで...私の質問は次のようなものです:ユーザーのページ DOM を操作しながら、C# IE BHO でコードを非同期に実行することは可能ですか?何人かの友人に聞いてみましたが、ほとんどの人がその可能性は低いと言っていました。私は C/VB.net/JS/AS から来たので、COM と C# に関してはまだ初心者です。
ありがとう!
-トム
解決
DOM オブジェクトを作成したスレッドからワーカー スレッドにマーシャリングする必要があります。 ここ は、COM と C# がどのように連携するかを非常に詳しく説明しています。
すべての IE DOM オブジェクトは STA オブジェクトです。