Tuesday, April 10, 2007
COM, Apartments, and Windows Presentation Foundation
As it turned out, however, COM made its way into Windows Presentation Foundation, and guess what, in its worst form.
One of the ugliest concepts in COM is the threading model. A component must declare a threading model (STA, Apartment, Free, Both, Neutral). Each thread must also initialize the COM engine by calling either CoInitialize (mostly legacy stuff) or CoInitializeEx, specifying the threading model it's gonna use.
When calls are made among uncompatible threading models, some proxy stuff kicks in , and the call is executed in a different thread (if you ever wondered why your single-threaded application, using COM, happens to create half a dozen threads under your shoulders, that's why).
So, for instance, in the following trivial case:

if Main calls CoInitializeEx specifying Apartment Threading, any direct call from Main to C1 will be executed in a different thread (yes, free threaded components cannot be called directly by apartment-threaded threads; you need "both" or "neutral" for that). Any direct call from Main to C2 will be executed in the same thread. If you change the parameter in CoInitializeEx to free threaded, of course, the opposite will happen: any call to C2 will be executed in a different thread. Whatever you do, any call from C1 to C2 will execute in a different thread, as the two threading models are not compatible. You can easily experiment with a little C++/ATL code, by simply logging the thread ID inside function calls.
I won't go in further details about the subtle differences between "free", "both", and "neutral": this stuff is well-documented, although too many developers never had the time or the will to learn it with the necessary depth. Luckily, we might say, this is old stuff, .NET has come to age and we can finally forget about apartments.
Turns out things are not that simple. Many companies have old, unmanaged C++ applications, and want to extend them with .NET components. This works fine, especially when you use C++/CLI as the glue language. Windows Forms components are (as far as I've seen) threading-model agnostic: indeed, you can take a Windows Form application, change the threading model attribute from STA to MTA, and (as far as I've seen) everything works fine. Not so with Windows Presentation Foundation. If you try to use WPF from an MTA thread, you get an error message, stating that the only supported threading model is STA. That's absurd to say the least, but I guess it's what you get when you involve an IUnknown worshipper (and proudly so) in the design of some new technology. Dear Microsoft, any chances you're gonna fix this?



