In the COM (Component Object Model) threading model, also known as an “apartment” model, an object resides in the same apartment during runtime. We access it either via STA (Single-Threaded Apartment) or MTA (Multi-Threaded Apartment) threading schemes.
In this tutorial, we’ll explain COM apartments and their two threading models: STA and MTA.
2. COM Apartments
Component Object Model (COM) is an object-oriented model for creating software components that can be easily distributed, are platform-independent, and communicate with one another.
While creating or manipulating a COM object, COM defines an apartment around it. In essence, that’s like drawing a boundary around it. As a result, a thread wanting to interact with the object must establish a relationship with the corresponding apartment. The purpose of an apartment is to enable COM to serialize method calls to an object that isn’t thread-safe.
Calls from Thread 1 directly access interface A of Object 1 since they share the same apartment. An interface between a thread and an object converts parameters passed to make them understandable for the object.
2.1. The Proxy/Stub Pair
In contrast, Thread 2 accesses the interface B of Object 2 via the proxy/stub pair since they aren’t in the same apartment. Proxy is an interface residing in the client apartment, and a stub is an interface in the server apartment. A proxy/stub pair is responsible for interpreting the parameters of a function call to the server and interpreting results from the server.
Additionally, COM marshals (converts) the interface pointer to the apartment of Thread 2 because it’s outside of Thread 1’s apartment. That is necessary because COM cannot know beforehand what particular interfaces any object implements.
Objects in different apartments cannot communicate directly and require marshaling of any communication between them. Hence, we can choose between COM’s default marshaling or write our own proxy and marshaling routines.
COM’s default stub generation uses an interface description language (IDL) to define the interface between the client thread and server object. The IDL marks each argument as input, output, or both. Only input arguments are copied to the server whereas the output ones are copied to the client.
3. Single-Threaded Apartments (STAs)
In an STA, only the thread that created the apartment may access the objects in it. A thread can’t access other apartments or alter the concurrency model of an apartment it created.
Here, COM performs most of the work of synchronizing access by other threads:
The stars in the diagram represent objects within an apartment (blue rectangle), and T1 – T4 represent threads trying to access the objects. However, only T1 gains access to the objects, while T2 – T4 wait in a queue.
3.1. Pros and Cons
Only a single thread can be executed: other threads within an apartment wait in the queue. Further, in STA, threads need a proxy to communicate.
In general, the STA model is useful when the COM object cannot handle its own synchronization.
Additionally, an apartment can host an unlimited number of objects but can service only one call at a time.
4. Multi-Threaded Apartments
The development of MTA is complex because calls to an object are not synchronized by COM, but by the object itself.
Here, we have a single apartment that can hold multiple threads and objects: they can interact directly without a proxy.
Further, it’s possible for multiple threads to access an object and change its data concurrently. As a result, we need to synchronize access to all objects to protect the data’s consistency:
T1 – T3 represent threads trying to access the objects in an apartment. In the MTA model, the threads can get access to the apartment directly and there’s no queue. Furthermore, an application may only contain one MTA. In contrast, it may have multiple STAs.
4.1. Pros and Cons
In MTA, all available threads within an apartment can be executed. They can communicate directly. We use this model when a COM object can handle its own synchronization.
However, the MTA model leads to a slower execution even though it applies synchronization only for the objects for which it’s necessary.
5. STA vs MTA
Let’s summarize the differences between the STA and MTA models:
This article talked about STA and MTA threading models and their pros and cons. While both models are equally important, we prefer STA when the COM object at hand can’t handle its own synchronization. Conversely, we need an MTA model for the COM object that can handle its own synchronization without marshaled calls.