One of complications for STA COM interfaces that they have thread affinity and any function from that interface should be called only from that thread. For example, imagine that main thread actively using some COM interfaces. And in some moment GC thread started to release unused interfaces.

But GC cannot call Release function of that interface in GC finalizer thread. GC thread should switch to main thread to call Release. This is quite slow and main thread could be busy. In case when there are a lot of interfaces went on .NET side it can create huge queue of interfaces waiting for their release and there could be some other objects waiting for finalizer to be called.

As mitigate that,

Another thing that developer should be aware when consuming COM interface is apartment. It is quite long topic and I will not explain it in detail. For today discussion let’s talk about STA. If you never use COM interface in .NET from different threads you can ignore this post.

STA means single thread apartment. Normally main thread has STA. COM interface that arrives to .NET runtime usually will be marked as STA. It means that that COM interface will be used only from thread it originally passed to. It called thread affinity. There are ways to change that behavior, but it will be in later posts.

As result when you call any function on STA COM interface and current thread is not one that originally received that interface then .NET runtime will attempt to switch to that thread.

COM in .NET is very tricky to do properly, and it is source of a lot of confusions. It is quite extensive area and I will try to explain stuff I learnt from it. I would like to mention that all that I got from practice and from exploring source code of CLR and call stacks in WinDbg. But some conclusions could be wrong so use it at own risk.

Firstly, we have to start with basics. Let’s talk about case when .NET code consumes some external COM object.

.NET cannot consume COM interfaces directly, so when COM interface crosses .NET boundary runtime will create special structure called Runtime Callable Wrapper (RCW for short) and .NET native objects (it called