I need some help understanding the difference between STA and MTA with respect to the winform and console application. I am using a third party COM interface to execute functions in parallel, using parallel.invoke. When i do this in console application everything works fine and code actually runs in parallel. But when i do the same thing in Winform it's sequential, and if i remove the STAtrhread tag above the entry point of winform , it start to work fine in parallel. Can anyone explain this behavior?,Any suggestions would be nice!
-
@stakx - It's true that a Winforms "Main" will be STA, and that you shouldn't change it. The solution, if you need MTA, is to spawn a thread, then use MTA components from the thread: http://stackoverflow.com/questions/1521816/winforms-one-com-object-needs-an-stathread-the-other-needs-an-mtathread-how-c – paulsm4 Jul 11 '12 at 19:55
-
Thanks, I will try this out..But i still do not understand as why it's working in console application.what threading model console application uses for COM?, i don't know if it's a valid question – user1514077 Jul 11 '12 at 20:52
2 Answers
COM has a feature that's entirely missing in .NET. A COM class can specify whether it is thread-safe or not. It does so with a key in the registry named ThreadingModel. Just like most .NET classes, the vast majority of COM classes are not thread-safe so they specify "Apartment". Which is a somewhat obscure term that implies "only call me from the thread on which I was created". Which automatically provides thread-safety.
To make that work, a thread that creates COM objects has to indicate what kind of support it is willing to provide for COM classes that are not thread safe. An STA thread is a safe home. Requirement is that the thread pumps a message loop, like any UI thread does. The message loop is the mechanism by which COM marshals a call from a worker thread to the thread that created the object. A thread that joins the MTA specifically says it does not provide support.
COM has to do something about MTA threads, they are not suitable for COM objects that are not thread safe. It creates a new thread, an STA thread to give the COM object a safe home. That's quite inefficient, every method call has to be marshaled. And risky, a COM class may still be thread-unsafe if its objects share state internally.
So what's happening in your Winforms case is that you created all the objects on the main thread, which is an STA. And make calls from parallel worker threads, those calls all get marshaled and serialized back to the STA thread. Inevitably, they execute one-by-one and you get no concurrency.
In your Console case, you created them on an MTA thread. So COM is forced to create threads for each object. The method calls on your worker threads are still marshaled, but now to multiple threads. So now you do get concurrency, at the cost of significant overhead, a bunch of extra threads. And the risk of failure when the server shares state internally.
Make the Winforms case the same as the Console case by creating the COM objects on a worker thread. Do test it very thoroughly.

- 922,412
- 146
- 1,693
- 2,536
-
Very good explanation. I was trying to say the same thing - you said it much, much better :) – paulsm4 Jul 11 '12 at 22:35
-
@hans thanks for such a nice explanation!. I tried out the thing you mentioned. That didn't work. I created four worker thread but it's like code is undeteced,I also tried this changing the apartment state of thread to MTA but that didn't work , Please help me out here. have no clue what's happening :@. I thought defining a MTA worker thread should work but it isn't , When i check in the IO moninter provided by the third party whose COM interface i am using the calls never take place.. – user1514077 Jul 12 '12 at 08:00
-
OK, i was approaching it wrong, before i made local copy of object via the objects i made earlier. I changed it and created COM objects on worker threads, It worked like a charm!!, thanks alot !!! – user1514077 Jul 12 '12 at 12:40
STA and MTA are both "threading models" for COM/ActiveX, dating back to the mid 1990's.
Here's a good link:
- STA:
A process has one single-threaded apartment (STA) for each thread that called CoInitialize. Each of these apartments, in turn, may have zero or more COM objects associated with them. As the name implies, however, only one specific thread (the thread that created the apartment by calling CoInitialize) may directly access the objects within the apartment
- MTA:
Although multi-threaded apartments, sometimes called free-threaded apartments, are a much simpler model, they are more difficult to develop for because the developer must implement the thread synchronization for the objects, a decidedly nontrivial task. On the positive side, removing an STA's synchronization mechanism gives the developer much finer control over the use of thread synchronization. They can apply it where it is actually needed rather than taking the very conservative approach of STAs, which synchronize access to the entire apartment.
One issue is choosing the best threading model for your component (the default is STA, IIRC). Another issue is what the runtime will do if you need to marshal data between your component and a component that uses a different threading model. The link above discusses both.

- 114,292
- 17
- 138
- 190