我读到了公寓模型,但当我试图理解以下内容时,它仍然让我感到困惑:谁的公寓决定了公寓模型?是线程的套间还是创建对象的套间?
考虑以下场景:
我创建了只有一个接口(interface)的 C++ ATL COM dll,即
ISimpleCom
,我有一个实现该接口(interface)的类,它只有一个方法test();
此类公开继承自CComObjectRootEx<CComSingleThreadModel>
设置STA公寓。在 C# WinForms 项目中引用此 DLL,并创建
SimpleCom
MTA 线程(不是 UI 线程)上的对象。 问题是: 假设 UI 线程调用test()
在这个对象上,它会被编码到创建对象的线程还是在 UI 线程上执行?- 如果它遵循对象 COM 单元,则应将此调用编码到创建该对象的线程,因为它是一个 STA 对象。
- 如果在创建 MTA 线程单元之后,它应该在 UI 线程上执行。
哪一个是正确的?
最佳答案
简单规则:
- 一个线程可能是零个或一个单元的成员
- 单线程单元 (STA) 由单线程组成,MTA - 由一个或多个线程组成,但每个进程最多可以有一个 MTA
- 线程在 COM 初始化时“加入”单元
所以一段代码要么在STA(在STA线程上)执行,要么在MTA中执行,要么线程还没有用COM初始化。当您通过 COM 实例化对象时,COM 会将公寓模型与调用 API 的公寓类型相匹配。
This class publicly inherit from CComObjectRootEx which sets STA apartment.
没有。这与设置公寓模型无关。 CComSingleThreadModel
表示此类使用简单的基类,这有利于对象在 STA 上运行 - 特别是在访问对象的引用计数器时它不会使用 InterlockedXxx API 或关键部分,因为类是假设生活在单线程中。这只是设置了COM类的套间模型,并不表示这个类要运行在STA上,只是提供了合适的基类。
ATL COM DLL 托管类的单元模型将在 .RGS 文件中指示,与 COM 类相关联,并将与 DLL 注册合并到注册表中。如果这是“公寓”模型,那么...
create the SimpleCom object on a MTA thread (not the UI thread).
... COM 会发现它不能直接在调用线程上实例化,因为该线程属于 MTA。因此 COM 将在工作 STA 线程上实例化,并将创建一个代理/ stub 对以将请求的接口(interface)编码到调用方 MTA 中。
关于c# - 对象公寓与线程公寓,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18977278/