STA or MTA for indirectly used COM Objects

孤街浪徒 提交于 2019-12-24 18:15:20

问题


I think I understand the apartment concept and why STA or MTA is used, however a question came up for which I found no solution so far.

If my application uses COM Objects under the hood, for example from third party libraries, how do I know if I can use MultiThreaded-Appartment (MTA)? In that case, I have no Idea if those objects are thread safe, so do I need to go with STA, just to be on the safe side?


回答1:


Your ability to use certain COM interface pointer on STA or MTA thread code depends on whether you at all cab obtain this pointer on this thread. If you can get the point on STA (or MTA) thread - you are good to use it further, provided that you don't pass it directly to another apartment.

If COM server is registered in certain way that you cannot obtain a pointer due to apartment type mismatch (typical case: STA thread and COM server is registered using "free" apartment model) then COM will attempt to marshal the pointer for you. If marshaling is successful, your code receives the pointer and you are good to go from there. Otherwise you get an error, and your attempt to do the same from another apartment succeeds. Basically, this is the only reliable generic method to obtain the answer on being able to use specific COM interface on STA or MTA thread.

In more specific case of instantiating a COM object, you can look up its registry information to see whether instantiation matches your apartment type. Out-of-process servers will provide you COM interface pointers through marshaling in any event, so any client side apartment will be able to consume this server.

There is no question of whether server objects are thread safe. If their COM registration is correct (esp. that STA in-proc server does not announce Free/Both registration) and marshaling is available, thread safety is included for free.




回答2:


Registered COM objects will belong to an apartment according to the ThreadingModel field (there's another article about COM apartments with a bigger, perhaps simpler table).

Basically, the ThreadingModel tells to which apartment the newly created object will belong to:

  • Not specified

    Main STA (the first CoInitialized STA; if none exists, COM creates one, called the host STA)

  • Apartment

    An STA (if we're in an STA, it'll be it, otherwise the host STA)

  • Free

    An MTA (if we're in the MTA, it'll be it; otherwise, COM creates it, called the host MTA)

  • Both

    Whatever is the current apartment

  • Neutral

    The neutral apartment

If you might be using MTA objects and you doubt if they're "thread-safe" (this typically means it will use an instance level lock on each method/property call), then you can't really do much about it. For instance, you could have multiple STAs accessing the same MTA object concurrently.

Making calls from an STA doesn't necessarily give you this thread safety, unless you guarantee there are no other STAs and no one else is using the same objects.

The "guarantee" works the other way around: all calls made to an STA will be sequential. Even so, re-entrant calls are allowed while the STA makes an inter-apartment call, so this is not really a lock-like guarantee.

The call serialization is really coarse, because it's at the apartment level, so all calls to the same STA, no matter the object, will be executed one at a time (but possibly one over the other in a re-entrant way).


EDIT: Call re-entrancy can be controlled with an IMessageFilter.



来源:https://stackoverflow.com/questions/27783163/sta-or-mta-for-indirectly-used-com-objects

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!