Why would I use “Both” COM threading model instead

2019-01-23 17:03发布

问题:

According to this article if I register my COM object with either "Both" or "Free" threading model that object must be completely thread-safe. Specifically all accesses to global shared variables must be synchronized and all accesses to member variables must also be synchronized. That's a lot of effort.

Now I understand that being able to register my object as using "Free" threading model is advantageous and might be worth paying the price of making it completely thread-safe. But why would I want to do all the same and register my object using "Both" threading model instead? What would be the advantage? How do I choose between "Both" and "Free"?

回答1:

Both Threading Model

The main reason for marking your component as supporting threading model "Both" is for performance improvements when the component is being called from a Single Threaded Apartment (STA).

If you mark your component as MTA and your component is created from within a STA then your component will be created in a separate MTA apartment and the "resultant inter-apartment marshaling might degrade performance enough to negate all the work put into making an efficient, free-threaded component". However, if your component's threading model is marked as "Both" then it will be created inside the apartment of the STA object and accessed directly.

So if you think your component may be called from within a STA (all VB6 COM objects are STA) you might want to mark the threading model as "Both".

A good KB article on OLE Threading Models.

Free Threading Model

You might want to use a "Free" thread model if your component uses other components that are marked as "Free". If your component was marked as "Both" then there could be excessive apartment switching between the "Both" component running in the STA and the MTA. As a general rule, try to create the component as close to the caller as possible (i.e. same apartment) while functioning properly under all scenarios.

Another situation that would warrant marking your component as "Free" is if it explicitly blocks (e.g. Thread.Sleep). If the component is marked as "Both" and instantiated in a STA then the component would block the STA message pump.

Other Considerations and Scenarios

If you are planning on using the component in IIS, then there are other things to consider. For IIS, "Both" is the recommended setting. Mainly to avoid locking issues with Apartment threaded components, performant access to COM+ ObjectContext and the fact that "Free" threaded components use the system security context (if you require access to the user's security context). See Selecting a Threading Model for Components in IIS for more info about IIS threading considerations.

Other things to consider are COM+ support and how your components behave if they are run in COM+ and whether interface pointers are passed and stored.

An excellent article is COM Threading and Application Architecture in COM+ Applications. It has a COM+ focus but also discusses COM. For your question, read the section entitled "Threading Model Recommendations". Microsoft has removed the original article so I'm linking to a copy.