Could you explain STA and MTA?

前端 未结 7 2117
梦如初夏
梦如初夏 2020-11-22 04:12

Can you explain STA and MTA in your own words?

Also, what are apartment threads and do they pertain only to COM? If so, why?

7条回答
  •  有刺的猬
    2020-11-22 04:58

    It's all down to how calls to objects are handled, and how much protection they need. COM objects can ask the runtime to protect them against being called by multiple threads at the same time; those that don't can potentially be called concurrently from different threads, so they have to protect their own data.

    In addition, it's also necessary for the runtime to prevent a COM object call from blocking the user interface, if a call is made from a user interface thread.

    An apartment is a place for objects to live, and they contain one or more threads. The apartment defines what happens when calls are made. Calls to objects in an apartment will be received and processed on any thread in that apartment, with the exception that a call by a thread already in the right apartment is processed by itself (i.e. a direct call to the object).

    Threads can be either in a Single-Threaded Apartment (in which case they are the only thread in that apartment) or in a Multi-Threaded Apartment. They specify which when the thread initializes COM for that thread.

    The STA is primarily for compatibility with the user interface, which is tied to a specific thread. An STA receives notifications of calls to process by receiving a window message to a hidden window; when it makes an outbound call, it starts a modal message loop to prevent other window messages being processed. You can specify a message filter to be called, so that your application can respond to other messages.

    By contrast all MTA threads share a single MTA for the process. COM may start a new worker thread to handle an incoming call if no threads are available, up to a pool limit. Threads making outbound calls simply block.

    For simplicity we'll consider only objects implemented in DLLs, which advertise in the registry what they support, by setting the ThreadingModel value for their class's key. There are four options:

    • Main thread (ThreadingModel value not present). The object is created on the host's main UI thread, and all calls are marshalled to that thread. The class factory will only be called on that thread.
    • Apartment. This indicates that the class can run on any single-threaded-mode thread. If the thread that creates it is an STA thread, the object will run on that thread, otherwise it will be created in the main STA - if no main STA exists, an STA thread will be created for it. (This means MTA threads that create Apartment objects will be marshalling all calls to a different thread.) The class factory can be called concurrently by multiple STA threads so it must protect its internal data against this.
    • Free. This indicates a class designed to run in the MTA. It will always load in the MTA, even if created by an STA thread, which again means the STA thread's calls will be marshalled. This is because a Free object is generally written with the expectation that it can block.
    • Both. These classes are flexible and load in whichever apartment they're created from. They must be written to fit both sets of requirements, however: they must protect their internal state against concurrent calls, in case they're loaded in the MTA, but must not block, in case they're loaded in an STA.

    From the .NET Framework, basically just use [STAThread] on any thread that creates UI. Worker threads should use the MTA, unless they're going to use Apartment-marked COM components, in which case use the STA to avoid marshalling overhead and scalability problems if the same component is called from multiple threads (as each thread will have to wait for the component in turn). It's much easier all around if you use a separate COM object per thread, whether the component is in the STA or MTA.

提交回复
热议问题