为什么我要使用“Both” COM线程模型而不是“Free”?

13
根据这篇文章的说法,如果我将我的COM对象注册为“Both”或“Free”线程模型,则该对象必须完全支持多线程。具体来说,对于所有全局共享变量的访问都必须进行同步,对于成员变量的所有访问也必须进行同步。这需要付出很大的努力。
现在我理解了,将我的对象注册为使用“Free”线程模型是有利的,而且可能值得付出使其完全支持多线程的代价。但是,为什么我仍要使用“Both”线程模型并做同样的事情呢?这有什么优势?我如何在“Both”和“Free”之间进行选择?
1个回答

22

双线程模型

将组件标记为支持"Both"线程模型的主要原因是在从单线程公寓(STA)调用组件时提高性能。

如果将组件标记为MTA,并且该组件是在STA中创建的,则该组件将在单独的MTA公寓中创建,而"结果的跨公寓封送可能会降低性能,从而抵消所有制作高效的自由线程组件所做的工作"。但是,如果将组件的线程模型标记为"Both",则它将在STA对象的公寓内创建并直接访问。

因此,如果您认为您的组件可能会从STA中调用(所有VB6 COM对象都是STA),则您可能希望将线程模型标记为"Both"。

一个很好的关于OLE线程模型的KB文章。

自由线程模型

如果您的组件使用其他标记为"Free"的组件,则您可能希望使用"Free"线程模型。如果将您的组件标记为"Both",则"Both"组件在STA中运行并与MTA之间可能存在过多的公寓切换。通常情况下,尽可能在调用者附近创建组件(即相同的公寓),同时在所有情况下正常工作。

另一种需要将组件标记为"Free"的情况是如果它显式阻塞(例如Thread.Sleep)。如果将组件标记为"Both"并在STA中实例化,则该组件将阻塞STA消息泵。

其他注意事项和场景

如果您计划在IIS中使用组件,则有其他要考虑的问题。 对于IIS,“Both”是推荐的设置。 主要是为了避免与公寓线程组件锁定问题,对COM + ObjectContext的高效访问以及“Free”线程组件使用系统安全上下文(如果需要访问用户的安全上下文)。 有关IIS线程考虑因素的更多信息,请参见选择IIS组件的线程模型

其他要考虑的事项是COM +支持以及如果在COM +中运行它们时组件的行为方式,以及是否传递和存储接口指针。

一篇优秀的文章是COM+应用程序中的COM线程和应用程序架构。 它专注于COM +,但也讨论了COM。 针对您的问题,请阅读标题为“线程模型建议”的部分。 Microsoft已删除原始文章,因此我链接到了一份副本。


2
这是一个很好的解释,但我现在不明白为什么我会将我的对象标记为“Free”而不是“Both”,因为看起来“Both”更有优势。 - sharptooth
1
因为您可能希望在MTA中“强制”它,即它将被MTA中的许多其他对象访问,并且您不希望这些对象使用代理来访问由VB6消费者创建的STA上的您的对象。 - wqw
如果有两个线程 - 一个STA和一个MTA,都调用CoCreateInstance(),那么...如果一个对象被标记为"Both",则在STA和MTA中分别创建一份副本。从Thread1到STA的调用和从Thread2到MTA的调用是直接的,其他调用通过代理传递。如果该对象被标记为"Free",则两个副本都在一个MTA中,只有从Thread1到MTA的调用通过代理传递,其他调用是直接的。这很酷,但为什么对象要强制执行后者,而不让它成为客户端的问题呢? - sharptooth
@sharptooth 如果你的对象需要 MTA,那么你需要告诉 COM 它需要在 MTA 中。答案给出了一个例子,如果你要执行阻塞操作,那么你需要在 MTA 中。 - user253751

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接