How to pass an ADO Recordset (or any COM object) across thread boundaries?

夙愿已清 提交于 2019-12-12 13:17:53

问题


i have an ADO Recordset object that is created in a background thread:

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;

And then the Recordset is handed to my "main" thread:

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;

i also could have done:

var 
   global_Recordset: _Recordset;

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

Either way, a thread that didn't create the COM object is now using it. From the main thread:

global_Recordset .Fields['TheTimeIs'].Value;

COM forbids accessing COM objects from apartments (in this case: threads) that did not create the object.

What is the correct way to marshal in in-process COM object interfaces across apartment boundaries?


回答1:


The correct way to pass a COM object across apartments is to marshal the interface pointer, which can be done in one of two different ways:

  1. Have the worker thread call the CoMarshalInterThreadInterfaceInStream() function and pass the resulting IStream pointer to the UI thread, which then calls the CoGetInterfaceAndReleaseStream() function.

  2. Use the IGlobalInterfaceTable interface. Have the worker thread create the interface and call its RegisterInterfaceInGlobal() method and pass the resulting cookie to the UI thread, which then creates the interface and calls its GetInterfaceFromGlobal() and RevokeInterfaceFromGlobal() methods.



来源:https://stackoverflow.com/questions/17351347/how-to-pass-an-ado-recordset-or-any-com-object-across-thread-boundaries

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!