Multi-Threading And COM
magazine.com/samples/comthread/comthreading.htm#Bio">Brian Long ()
This article first appeared in , Issue 60 (August 2000).
Table Of Contents
However, most information concentrates on dealing with COM in simple, non-threaded applications. Very little information exists on the subject of multi-threaded COM applications for the Delphi developer (although see ). Sure enough, there is quite a lot of printed information on the subject for C++ developers, but that is not entirely surprising.
This article tries to overcome this lack of information and attempts to provide an understanding of the concepts, terminology and issues involved in multi-threaded COM programming. It does not try and teach you safe multi-threaded programming which warrants a separate examination. Instead it assumes you have an appreciation of the general issues of multi-threaded programming, such as the necessity to protect or synchronise access to resources accessible from more than one thread. If not, you should investigate Windows synchronisation primitives such as mutexes, semaphores, events, critical sections (for example in ) and the Delphi TMultiReadExclusiveWriteSynchronizer class.
Before we start on the subject, I should mention that Delphi 3 did not have built-in support for thread-safe COM objects. Delphi 4 added some support, although it needed a little . Delphi 5 was the first version to for thread-aware COM objects in the RTL.No, I’m not about to launch into some spiel about American city dwellings. Instead, an apartment is an important thread-related concept in COM. When you read about multi-threaded COM programming you might find it all rather confusing due to the constant references to various types of apartments, so I feel it prudent to start by investigating what an apartment is.
As Windows developers, you are probably reasonably comfortable about the way parts of applications are managed by Windows. When a program is launched, Windows creates a process "object" containing information about that process. I placed the word object in quotes because whilst it may well be stored as an object, programmers do not have access to it in such a form.
Each process object has a unique identifying number, or process identifier (a DWord or unsigned 32-bit number). Applications can also gain varying degrees of access to the process object by getting a handle to it, which is called a process handle (a THandle, which again is a 32-bit number).
When the program initiates any threads, be it the first (or primary) thread of an application, or additional (secondary) threads, Windows similarly manages them with thread objects. These contain the state information of the thread, or the thread’s context. These thread objects also have unique identifiers (thread identifiers) and can be accessed through a thread handle.
It perhaps should be mentioned at this point that the Delphi VCL is almost entirely not thread-safe. You should therefore use some form of synchronisation to access any VCL objects from any thread other than the primary thread. In a normal thread class (inherited from TThread), you would use the Synchronize method.
When an application thread creates a window, Windows also manages that via some internal data structure containing information about the window, which we refer to with a window handle (a HWnd or THandle).
Processes, threads and are fairly old hat as Windows-managed entities. Apartments, are not as common to most, despite any application that deals with COM containing at least one of them. Apartments also reside in an executable and are also managed by Windows, but we programmers do not have e