如何跨线程边界传递ADO Recordset(或任何COM对象)?

时间:2013-06-27 19:11:02

标签: delphi com ado

我有一个在后台线程中创建的ADO Recordset对象:

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传递给我的" main" 主题:

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对象接口中编组正确的方法是什么?

1 个答案:

答案 0 :(得分:4)

在公寓之间传递COM对象的正确方法是编组接口指针,这可以通过两种不同的方式之一完成:

  1. 让工作线程调用CoMarshalInterThreadInterfaceInStream()函数并将生成的IStream指针传递给UI线程,然后调用CoGetInterfaceAndReleaseStream()函数。

  2. 使用IGlobalInterfaceTable界面。让工作线程创建接口并调用其RegisterInterfaceInGlobal()方法并将生成的cookie传递给UI线程,然后创建接口并调用其GetInterfaceFromGlobal()RevokeInterfaceFromGlobal()方法。