1

IEを開くための継承されたコードがいくつかあり、いくつかの問題があります。これが私が持っているものです:

IEUnit.pas (フォームなし) には、LoadIE および OpenIE のルーチンがあります。

別のスレッドから OpenIE が呼び出され、次のようになります

procedure OpenIE(URL: OleVariant; FieldValues: string = '');
var ie : IWebBrowser2; // <-- This should become "global" variable for the IEUnit
begin
  ie := CreateOleObject('InternetExplorer.Application') as IWebBrowser2;
  ie.Navigate2(URL, Flags, TargetFrameName, PostData, Headers);
  ShowWindow(ie.HWND, SW_SHOWMAXIMIZED);
  ie.Visible := true;
  ...
end;

ユニットに「グローバル」つまり変数を持ち、LoadIE ルーチンを次のように記述したいと思います。

LoadIE は FormCreate (メイン スレッド) から呼び出す必要があります。

「グローバル」つまりオブジェクトを作成するだけです

  ie := CreateOleObject('InternetExplorer.Application') as IWebBrowser2;

したがって、OpenIE関数はそれを作成する必要はなく、使用するだけです(目的は速度を上げることです)

問題は、2 つの異なるスレッドから同じ OLE オブジェクトにアクセスする方法です。1 つはオブジェクトを作成し、もう 1 つはそれを使用します。


スレッドを処理しないコードを記述すると、エラーが発生します

例外クラス EOleSysError とメッセージ「アプリケーションは、別のスレッド用にマーシャリングされたインターフェイスを呼び出しました」

スレッドを処理するにはどうすればよいですか (私はスレッドの経験がありません。いくつかの読書とビデオのリンクは大歓迎です)。

前もって感謝します

4

4 に答える 4

6

MTA モデルの COM サーバーは、関連付けられたアパートメント内からのみ使用できます。エラーの説明と次のアドバイスを次に示します。

あるアパートメントから別のアパートメントにインターフェイス ポインター (ダイレクト ポインターまたはプロキシ ポインター) を転送する正しい方法は、COM のマーシャリング メカニズムを使用することです。ソース アパートメントは、 CoMarshalInterThreadInterfaceInStream()を呼び出して、インターフェイス ポインターを共有 (グローバル) ストリームにマーシャリングできます。宛先アパートメントは、 CoGetInterfaceAndReleaseStream()を呼び出すことによって、このインターフェイス ポインターを非整列化できます。

于 2012-10-11T13:58:07.503 に答える
3

ご存知のように、これは前回の質問の主題であったため、COM オブジェクトへのすべての呼び出しを同じスレッドから行う必要があります。当然の選択は、メインの GUI スレッドです。したがって、IWebBrowser2メイン フォームのOnCreateイベント ハンドラで を作成します。そして、ブラウザを表示する必要があるときはいつでもTThread.Synchronizeorを使用してください。TThread.Queue渡すコード、SynchronizeまたはQueueメイン GUI スレッドで実行されるコード。

匿名メソッドをサポートする最新バージョンの Delphi を使用していると仮定すると、次のように記述できます。

procedure TMyThread.ShowBrowser(const URL: string);
var
  Proc: TThreadProcedure;
begin
  Proc := procedure
    begin
      MainForm.Browser.Navigate2(URL, ...);
      ShowWindow(MainForm.Browser.HWND, SW_SHOWMAXIMIZED);
      MainForm.Browser.Visible := true;
    end;
  Queue(Proc);
end;
于 2012-10-11T14:03:24.893 に答える
2

非フリー スレッド COM オブジェクトは、そのオブジェクトが作成されたスレッドと同じスレッドでのみ使用できます。あなたの場合、処理を高速化するために、treadvarIWebBrowser2 型の単純なグローバル値を使用するか、TThread をオーバーライドするクラスのプロパティを使用します。

于 2012-10-11T14:42:59.157 に答える
1

CriticalSectionを使用して、OleObjectへのすべての呼び出しをラップします。また、Synchronizeを使用して、「その他」のスレッドからメインUIスレッドを呼び出します(これが例外を取得する理由です)。

于 2012-10-11T13:41:14.020 に答える