2

I've read lots about the Microsoft's threaded apartment model, but I'm still having a little trouble visualizing it.

Microsoft uses the analogy of living things living in an apartment. So, for STA, consider the following (I know it's a little silly).

  1. Assume thread = person and COMObject = bacteria. The person lives in the apartment, and the bacteria lives inside the person. So in STA-Land, a thread lives in the STA and the COMObject lives inside the thread, so in order to interact with the COMObject, one must do so by running code on the COMObject's thread.

  2. Assume thread = person and COMObject = cat. The person lives in the apartment, and the cat lives in the apartment with the person. SO in STA-Land, the thread and the COMObject at the same hierarchical level.

Q1. Which analogy above is correct, or if neither are correct, how would you describe the STA?

Q2. How would you describe the MTA?

Verax
  • 2,409
  • 5
  • 27
  • 42
  • 2
    @nonnb - that article is not about COM apartments it barely touches them. – Emond Jan 26 '12 at 07:10
  • possible duplicate of [Could you explain STA and MTA?](http://stackoverflow.com/questions/127188/could-you-explain-sta-and-mta) – ChrisWue Jan 26 '12 at 07:11

2 Answers2

3

I do not like these analogies. They are confusing.

You create an apartment.

If it is an STA there will be only one thread in the apartment so all the objects in that apartment will be executed on that single thread (so there is no concurrent execution in the objects in that apartment)

If it is an MTA there can be multiple threads in that apartment. So the objects in the MTA need to implement the synchronization explicitly if needed.

An object lives in one apartment. There can be multiple objects in the same apartment.

A very good read here

Emond
  • 50,210
  • 11
  • 84
  • 115
  • So if you call a STA object's method from some other thread, does that method execute on the Apartment's thread? – Verax Jan 26 '12 at 07:47
  • yes, the data of the calling thread will need to be marshalled. Read this: http://www.codeproject.com/Articles/9190/Understanding-The-COM-Single-Threaded-Apartment-Pa – Emond Jan 26 '12 at 07:52
3

It is not a great term. It actually describes thread behavior. A thread tells COM how it behaves in the CoInitializeEx() call, selecting between STA and MTA. By using STA, the thread promises that it behaves in a manner that suitable for code that is not thread-safe. The hard promises it makes are:

  • Never blocks execution
  • Pumps a message loop

Using MTA means a thread can do whatever it wants and does not make any effort to support code that is not thread-safe.

This matters first when a COM object gets created. Such an object contains a key in the registry that describes what kind of thread-safety it implements. The ThreadingModel key. By far the most common value for this key is "Apartment" (or is missing), telling COM that it doesn't support threading at all and that any calls on the object must be made from the same thread.

If the thread that creates such an object is in an STA then everything is happy. After all, the thread promised to support single threaded objects. If the thread is in the MTA then there's a problem, the thread said it didn't support thread-safety but still created an object that isn't thread-safe. COM steps in an creates a new thread, an STA thread that can support code that isn't thread safe. The code gets a proxy to the object. Any calls made on the object go through that proxy. The proxy code intercepts the call and makes it run on the STA thread that was created, thus ensuring the call is made in a thread-safe way.

As you can imagine, the job done by the proxy isn't cheap. It involves two thread context switches and a stack frame must be constructed from the function arguments to make the call. It must also wait until the thread is ready to execute the call. This is called marshaling, it is an easy 3 orders of magnitude slower than making a call that doesn't have to be marshaled. This perhaps also explains the reason an STA thread has those two requirements listed above. It cannot block because as long as it blocks that marshaled call cannot be made and makes deadlock very likely. And it must pump a message loop, that loop is what makes injecting a call into another thread possible.

So making a thread join the MTA is easy programming for you. But deadly to performance. An STA is efficient.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • "So making a thread join the MTA is easy programming for you. But deadly to performance. An STA is efficient." Surely you mean this the other way around? – Emond Jan 26 '12 at 14:16
  • I surely didn't. Note "is an easy 3 orders of magnitude slower". Writing code that supports free threading makes it fast. It's just that practically nobody knows how to do that and often can't due to restrictions in libraries they use. – Hans Passant Jan 26 '12 at 14:17
  • In my experience writing threadsafe code is difficult, so having a thread join an MTA is NOT easy programming. STA is safe but blocks other threads from running and might not be using all cores when the code in the STA is actually threadsafe. That is not efficient in my book, just easy, safe coding. – Emond Jan 26 '12 at 14:28
  • The person that writes the library is *not* the same as the one that writes the thread. You're reasoning from the library writer's point of view, COM apartments matter to the *consumer* of the library. "Easy, safe coding" is not exactly a bad thing. The COM threading model was explicitly invented to *help* write easy and safe code. There wouldn't have been any point to it otherwise. – Hans Passant Jan 26 '12 at 15:31
  • :) We agree, it is a matter of perspective. – Emond Jan 26 '12 at 16:49
  • Best succinct explanation of apartments and marshalling I've seen. However, I don't think STAs – antlersoft Oct 09 '15 at 18:20