我想我了解公寓的概念以及为什么要使用 STA 或 MTA,但是出现了一个问题,到目前为止我还没有找到解决方案。
如果我的应用程序在后台使用 COM 对象,例如来自第三方库,我如何知道我是否可以使用 MultiThreaded-Appartment (MTA)?在那种情况下,我不知道这些对象是否是线程安全的,所以为了安全起见,我是否需要使用 STA?
您在 STA 或 MTA 线程代码上使用特定 COM 接口指针的能力取决于您是否在该线程上获得该指针。如果您可以在 STA(或 MTA)线程上获得要点 - 您最好进一步使用它,前提是您不直接将它传递给另一个公寓。
如果 COM 服务器以某种方式注册,由于单元类型不匹配而您无法获得指针(典型情况:STA 线程和 COM 服务器使用“免费”单元模型注册),那么 COM 将尝试为您编组指针。如果封送成功,您的代码会收到指针,您可以从那里开始。否则你会得到一个错误,并且你尝试从另一个公寓做同样的事情会成功。基本上,这是获得能够在 STA 或 MTA 线程上使用特定 COM 接口的答案的唯一可靠的通用方法。
在更具体的实例化 COM 对象的情况下,您可以查看其注册表信息以查看实例化是否与您的公寓类型匹配。在任何情况下,进程外服务器都会通过编组为您提供 COM 接口指针,因此任何客户端单元都可以使用该服务器。
毫无疑问,服务器对象是否是线程安全的。如果他们的 COM 注册是正确的(尤其是 STA 进程内服务器没有宣布 Free/Both 注册)并且编组可用,则免费包含线程安全。
已注册的 COM 对象将根据ThreadingModel字段属于一个单元(还有另一篇关于 COM 单元的文章,它有一个更大、可能更简单的表)。
基本上,ThreadingModel 告诉新创建的对象将属于哪个单元:
未指定
主 STA(第一个CoInitialize
d STA;如果不存在,则 COM 创建一个,称为主机 STA)
公寓
一个 STA(如果我们在一个 STA 中,那就是它,否则就是主机 STA)
自由的
一个 MTA(如果我们在 MTA 中,就是它;否则,COM 创建它,称为主机 MTA)
两个都
无论现在的公寓是什么
中性的
中性公寓
如果您可能正在使用 MTA 对象并且您怀疑它们是否是“线程安全的”(这通常意味着它将在每个方法/属性调用上使用实例级锁定),那么您真的无能为力。例如,您可以有多个 STA 同时访问同一个 MTA 对象。
从STA 进行调用并不一定会给您这种线程安全性,除非您保证没有其他 STA 并且没有其他人使用相同的对象。
“保证”则相反:对STA 的所有调用都是连续的。即便如此,在 STA 进行公寓间调用时允许重入调用,因此这并不是真正的类似锁的保证。
调用序列化非常粗糙,因为它在单元级别,所以对同一个 STA 的所有调用,无论对象如何,都将一次执行一个(但可能以可重入方式一个在另一个之上)。
编辑:可以使用IMessageFilter控制呼叫重新进入。