3

バックグラウンド スレッドで作成された ADORecordsetオブジェクトがあります。

var
   conn: TADOConnection;
   rs: _Recordset;
begin
   conn := CreateDatabaseConnection();
   rs := conn.Execute(CommandText, cmdText, []);
   conn.Free;

   //Give the recordset to the UI thread
   //Don't forget to add a reference before we stuff it into a 32-bit variable
   rs._AddRef();
   PostMessage(hwndUIThreadWindow, WM_HeresTheRecordsetYouAskedFor, WPARAM(rs), 0);
end;

そして、 「メイン」スレッドRecordsetに渡されます。

procedure ExecuteComplete(var msg: TMessage); message WM_HeresTheRecordsetYouAskedFor;
var
   rs: _Recordset;    
begin
   rs := _Recordset(msg.wParam);
   //don't forget to remove the manually added reference
   rs._Release();

   ShowMessage(rs.Fields['TheTimeIs'].Value);
end;

私もできた:

var 
   global_Recordset: _Recordset;

var
   conn: TADOConnection;
begin
   conn := CreateDatabaseConnection();
   global_Recordset := conn.Execute(CommandText, cmdText, []);
   conn.Free;
end;

いずれにせよ、COM オブジェクトを作成しなかったスレッドが現在それを使用しています。メインスレッドから:

global_Recordset .Fields['TheTimeIs'].Value;

COMは、オブジェクトを作成していないアパートメント (この場合はthreads )からの COM オブジェクトへのアクセスを禁止します。

アパートメントの境界を越えてインプロセスCOM オブジェクト インターフェイスをマーシャリングする正しい方法は何ですか?

4

1 に答える 1

4

アパートメント間で COM オブジェクトを渡す正しい方法は、インターフェイス ポインターをマーシャリングすることです。これは、次の 2 つの方法のいずれかで実行できます。

  1. ワーカー スレッドでCoMarshalInterThreadInterfaceInStream()関数を呼び出し、結果のIStreamポインターを UI スレッドに渡します。UI スレッドはCoGetInterfaceAndReleaseStream()関数を呼び出します。

  2. インターフェイスを使用しIGlobalInterfaceTableます。ワーカー スレッドでインターフェイスを作成し、そのRegisterInterfaceInGlobal()メソッドを呼び出して、結果の Cookie を UI スレッドに渡します。UI スレッドはインターフェイスを作成し、そのメソッドGetInterfaceFromGlobal()RevokeInterfaceFromGlobal()メソッドを呼び出します。

于 2013-06-28T01:21:40.890 に答える