C# 对象公寓vs线程公寓
我读过关于公寓模式的书,但当我试图理解以下内容时,我仍然感到困惑:谁的公寓决定了公寓模式?是线程的单元还是创建对象的单元?C# 对象公寓vs线程公寓,c#,c++,com,atl,C#,C++,Com,Atl,我读过关于公寓模式的书,但当我试图理解以下内容时,我仍然感到困惑:谁的公寓决定了公寓模式?是线程的单元还是创建对象的单元? 考虑下面的场景: > p>我创建了C++的ATL COM DLL,它只有一个接口,即代码> ISPysECOM < /代码>,并且我有一个类,该接口只有一个方法测试()代码> 此类公开继承自设置STA单元的CComObjectRootEx 在C#WinForms项目中引用此DLL,并在MTA线程(而不是UI线程)上创建SimpleCom对象。 问题是: 假设UI线程调用此
考虑下面的场景:
CComObjectRootEx
SimpleCom
对象。
问题是:
假设UI线程调用此对象上的test()
,它将被封送到该对象创建的线程,还是将在UI线程上执行
- 如果它跟随对象COM单元,则应将此调用封送到创建该对象的线程,因为它是STA对象
- 如果它是在创建线程单元(MTA)之后执行的,那么它应该在UI线程上执行
- 线程可能是零个或一个单元的成员
- 单线程单元(STA)由一个或多个线程组成的单线程MTA组成,但每个进程最多只能有一个MTA
- 线程在COM初始化时“加入”单元
CComSingleThreadModel
表示,该类使用简单的基类,这有利于在STA上运行对象,特别是在访问对象的引用计数器时,它不会使用InterlockedXxx API或关键部分,因为假定该类位于单线程内。这确实设置了COM类的单元模型,但并不表示该类将在STA上运行,这只是提供了合适的基类
ATL COM DLL托管类的单元模型将在与COM类关联的.RGS文件中指示,并将与DLL注册合并到注册表中。如果这是“公寓”模式,那么
在MTA线程(而不是UI线程)上创建SimpleCom对象
。。。COM将看到它无法直接在调用线程上实例化,因为该线程属于MTA。因此COM将在worker STA线程上实例化,并将创建一个代理/存根对,以将请求的接口marhshal到调用方MTA中。因此,如果我理解正确,从我在文章中描述的场景来看,创建类的UI线程和MTA线程都不会执行test()。test()的执行将被封送到创建COM类的工作线程,而COM类在该线程中存在?它不会在MTA线程上执行。调用将被封送到工作线程中,如果是STA线程,则被封送到UI线程中。然后实际的方法将从那里执行。为了避免混淆,让我们对线程进行id:1-UI、2-MTA、3-Worker。因此COM对象是在线程#2上创建的,但由于它是MTA线程,因此它创建了线程id为#3的新STA工作线程。现在,UI线程yx 1调用COM的对象测试()方法,从您的答复测试()中,将被封送到线程3,并由该线程执行?作为C++程序员,实现COM类作为“自由线程”通常是非常可行的。这意味着它们可以同时在STA和MTA中运行,COM不会为代理而烦恼。只要您自己的代码是线程安全的,并且不从其他COM组件继承单元限制,这就行了。@MSalters:一个小的更正-它可能是“双线程的”。“自由线程”仅适用于MTA。“两者”是公寓线程模型。另一方面,对象可以嵌入“自由线程封送处理程序”,这是一种特殊类型的封送处理实现,它以原始形式在单元之间传递接口指针,从而消除代理。也许这就是你的意思。