1

我读到了公寓模型,但当我试图理解以下内容时,我仍然感到困惑:谁的公寓决定了公寓模型?是线程的公寓还是创建对象的公寓?
考虑以下场景:

  1. 我创建了只有一个接口的 C++ ATL COM dll ISimpleCom,并且我有一个类实现该接口,该接口只有一个方法test(); 此类公开继承自CComObjectRootEx<CComSingleThreadModel>它设置 STA 单元。

  2. 在 C# WinForms 项目中引用此 DLL,并SimpleCom在 MTA 线程(而不是 UI 线程)上创建对象。问题是:假设 UI 线程调用test()此对象,它将被编组到创建对象的线程还是将在 UI 线程上执行?

    • 如果它遵循对象 COM 单元,则此调用应封送到创建对象的线程,因为它是一个 STA 对象。
    • 如果它在创建 MTA 线程单元之后,它应该在 UI 线程上执行。

哪一个是正确的?

4

1 回答 1

2

简单规则:

  • 线程可能是零个或一个公寓的成员
  • 单线程单元 (STA) 由单线程 MTA 组成 - 一个或多个线程,但每个进程最多可以有一个 MTA
  • 线程在 COM 初始化时“加入”公寓

因此,一段代码要么在 STA(在 STA 线程上)执行,要么在 MTA 中执行,或者线程尚未使用 COM 初始化。当您通过 COM 实例化对象时,COM 会将公寓模型与调用 API 的公寓类型相匹配。

此类公开继承自设置 STA 单元的 CComObjectRootEx。

不,这与设置公寓模型无关。CComSingleThreadModel说这个类使用简单的基础,这有利于对象在 STA 上运行 - 特别是在访问对象的引用计数器时它不会使用 InterlockedXxx API 或关键部分,因为假设该类存在于单线程中。这确实设置了 COM 类的公寓模型,并不表示该类要在 STA 上运行,这只是提供了合适的基类。

ATL COM DLL 托管类的单元模型将在 .RGS 文件中指示,与 COM 类关联,并将通过 DLL 注册合并到注册表中。如果这是“公寓”模型,那么...

在 MTA 线程(不是 UI 线程)上创建 SimpleCom 对象。

... COM 将看到它不能直接在调用线程上实例化,因为该线程属于 MTA。因此 COM 将在工作 STA 线程上进行实例化,并创建一个代理/存根对来将请求的接口编组到调用者 MTA。

于 2013-09-24T09:33:09.753 回答