COM Threading Model

Concepts

The key to understanding the COM threading model (at least from the perspective of a COM programmer) lie in two concepts: how thread interactions are synchronized, and the 'locality' of COM objects.  Within COM, there are two types of threads.  The first one is an apartment thread, the second is a free thread.

We'll look at the apartment thread first.  One can think of an apartment as being an isolated box, which contains at most a single thread. The apartment is composed of that single thread, plus a Windows message queue, and some OS support to ensure that everything else deals with the apartment thread through the message queue, and never directly.  Because all  interaction is funneled through the message queue, all operations are serialized, and thus there is no need for synchronization within an apartment thread.  COM objects created within an apartment thread 'live' in that apartment - it's created there, does work during it's lifetime there, then is destroyed there.  If any other thread wants to interact with that object, an interface pointer will have to be marshalled to the other thread -- either by Windows, or you. Thus, COM objects within an apartment thread are 'local' to that thread.

Next, we'll examine free threads.  Between free threads, there's no synchronization other than what you provide. Also, COM objects (and interfaces) can be shared between free threads without having to marshal them, thus COM objects created by a free thread are in no way 'local' to that thread.  Note that although some books refer to there being a 'free thread apartment', so far as I can tell, that's pretty much a meaningless statement: think 'free thread' instead.  It is instructive to consider when marshalling/synchronization does and doesn't occur:
 
From To Synchronization provided by Windows? Marshalling Interfaces neccessary?
Apartment Apartment Yes Yes
Free Free None whatsoever No
Apartment Free None whatsoever Out-of-proc:yes, otherwise no
Free Apartment Yes Yes
 

Free Threads
As explained above, there is no mandatory serialization/synchronization between free threads, and free threads may pass objects/interface pointers to each other without having to marshal anything. (You can (and probably should) utilize synchonization between these threads -- Windows provides a number of synch.mechanisms) On the downside, this means that the same code may be executed by different threads at different times, which may be confusing.Free threads are created using the system call "CreateThread()".
Apartment Threads
Apartment threads need to marshall objects/interface pointers before passing them to other threads, and all messages/method invocations/etc are serialized behind the scenes. Thus, programming an apartment thread is easier since you don't have to worry about synchronization issues.  To make an apartment thread, call CreateThread(), then have the newly; created thread invoke CoInitialize() (or OleInitialize() ) (this initializes the Windows message queue, as well as internal structures used by COM)
The difference between Free Threads and Apartment Threads can be confusing when first looking at them, but they make sense eventually.

Free Threading Example


Apartment Threading example


All Rights Reserved 1997 by Michael William Panitz (mpanitz@cascadia.ctc.edu)
Home Page
Please note that OLE, COM, ActiveX, book titles, etc are NOT in any way reserved or trademarked by Mike, but instead belong to their resepective owners. The author would also like to gratefully acknowledge the MS Visual C++ help files as being a much appreciated source of information, particularly for function/interface prototypes, data type definitions, etc.