1

我想我了解公寓的概念以及为什么要使用 STA 或 MTA,但是出现了一个问题,到目前为止我还没有找到解决方案。

如果我的应用程序在后台使用 COM 对象,例如来自第三方库,我如何知道我是否可以使用 MultiThreaded-Appartment (MTA)?在那种情况下,我不知道这些对象是否是线程安全的,所以为了安全起见,我是否需要使用 STA?

4

2 回答 2

2

您在 STA 或 MTA 线程代码上使用特定 COM 接口指针的能力取决于您是否在该线程上获得该指针。如果您可以在 STA(或 MTA)线程上获得要点 - 您最好进一步使用它,前提是您不直接将它传递给另一个公寓。

如果 COM 服务器以某种方式注册,由于单元类型不匹配而您无法获得指针(典型情况:STA 线程和 COM 服务器使用“免费”单元模型注册),那么 COM 将尝试为您编组指针。如果封送成功,您的代码会收到指针,您可以从那里开始。否则你会得到一个错误,并且你尝试从另一个公寓做同样的事情会成功。基本上,这是获得能够在 STA 或 MTA 线程上使用特定 COM 接口的答案的唯一可靠的通用方法。

在更具体的实例化 COM 对象的情况下,您可以查看其注册表信息以查看实例化是否与您的公寓类型匹配。在任何情况下,进程外服务器都会通过编组为您提供 COM 接口指针,因此任何客户端单元都可以使用该服务器。

毫无疑问,服务器对象是否是线程安全的。如果他们的 COM 注册是正确的(尤其是 STA 进程内服务器没有宣布 Free/Both 注册)并且编组可用,则免费包含线程安全。

于 2015-01-05T16:11:48.657 回答
1

已注册的 COM 对象将根据ThreadingModel字段属于一个单元(还有另一篇关于 COM 单元的文章,它有一个更大、可能更简单的表)。

基本上,ThreadingModel 告诉新创建的对象将属于哪个单元:

  • 未指定

    主 STA(第一个CoInitialized STA;如果不存在,则 COM 创建一个,称为主机 STA)

  • 公寓

    一个 STA(如果我们在一个 STA 中,那就是它,否则就是主机 STA)

  • 自由的

    一个 MTA(如果我们在 MTA 中,就是它;否则,COM 创建它,称为主机 MTA)

  • 两个都

    无论现在的公寓是什么

  • 中性的

    中性公寓

如果您可能正在使用 MTA 对象并且您怀疑它们是否是“线程安全的”(这通常意味着它将在每个方法/属性调用上使用实例级锁定),那么您真的无能为力。例如,您可以有多个 STA 同时访问同一个 MTA 对象。

STA 进行调用并不一定会给您这种线程安全性,除非您保证没有其他 STA 并且没有其他人使用相同的对象。

“保证”则相反:STA 的所有调用都是连续的。即便如此,在 STA 进行公寓间调用时允许重入调用,因此这并不是真正的类似锁的保证。

调用序列化非常粗糙,因为它在单元级别,所以对同一个 STA 的所有调用,无论对象如何,都将一次执行一个(但可能以可重入方式一个在另一个之上)。


编辑:可以使用IMessageFilter控制呼叫重新进入。

于 2015-01-06T15:16:08.603 回答