C Sharp

COM Threading Models

When most people start programming in COM, they have little or no knowledge of the COM threading models and apartments. It isn't until they become much more experienced that they realize that the free-threadedmodel they've been using comes at a severe performance cost when an single-threaded apartment ( STA) client thread is used to create an multithreaded apartment ( MTA) object. In addition, programmers new to COM frequently aren't aware of thread safety and the impending danger that awaits them when concurrent threads access their COM components.-

Before a thread can call into a COM object, it has to declare its affiliation to an apartment by declaring whether it will enter an STA or MTA. STA client threads call CoInitialize(NULL) or CoInitializeEx(0, COINIT_APARTMENTTHREADED) to enter an STA, and MTA threads call CoInitializeEx(0, COINIT_MULTITHREADED) to enter an MTA. Similarly, in the .NET-managed world, you have the option of allowing the calling thread in the managed space to declare its apartment affinity. By default, the calling thread in a managed application chooses to live in an MTA. It's as if the calling thread initialized itself with CoInitializeEx(0, COINIT_MULTITHREADED). But think about the overhead and the performance penalties that would be incurred if it were calling a classic STA COM component that was designed to be apartment-threaded. The incompatible apartments will incur the overhead of an additional proxy/stub pair, and this is certainly a performance penalty.

To that end, you can override the default choice of apartment for a managed thread in a .NET application by using the ApartmentState property of the System.Threading.Thread class. The ApartmentState property takes one of the following enumeration values: -

  • MTA Multithreaded apartment
  • STA Single-threaded apartment
  • Unknown Equivalent to the default MTA behavior

You'll also need to specify the ApartmentState property for the calling thread before you make any calls to the COM object. Please note that it's not possible to change the ApartmentState once the COM object has been created. Therefore, it makes sense to set the thread's ApartmentState as early as possible in your code. The following code shows how that's done: -

// Set the client thread ApartmentState to enter an STA.
Thread.CurrentThread.ApartmentState =
    ApartmentState.STA;
// Create our COM object through the Interop.
MySTA objSTA = new MySTA();
objSTA.MyMethod()