Consumer Threading Responsibilities
Free-threaded consumers have the following threading responsibilities:
To call CoInitializeEx on each thread, with a null pointer as the first parameter and COINIT_MULTITHREADED as the second parameter, to initialize it as free-threaded.
When passing interfaces to other threads, to transfer pointers directly only when the other thread is free-threaded and when the pointers correspond to free-threaded objects.
The set of threads initialized as free-threaded acts similarly to a single big apartment, so pointers can be freely passed between these threads. To transfer a free-threaded object to a real apartment, it is recommended (but not required) that the pointer be marshaled at the source and unmarshaled at the destination. To transfer an apartment-threaded object to any free-threaded thread, it is necessary to marshal the pointer at the source and unmarshal it at the destination.
Apartment-threaded consumers have the following threading responsibilities:
To implement a message queue.
To call CoInitialize or OLEInitialize on the thread.
To always marshal pointers of OLE DB objects (and other COM objects) to other apartments by using CoMarshalInterface and CoUnmarshalInterface calls. Calls to these methods trigger the deployment of proxies and stubs by the COM infrastructure. Well-behaved apartment-model consumers may interact efficiently with free-threaded servers if the free-threaded server aggregates with a generic free-threaded marshaler that COM supplies by using CoCreateFreeThreadedMarshaler.