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?