2013-09-24 59 views
0

我阅读了关于公寓模型的内容,但当我试图了解以下内容时,它仍然让我感到困惑:谁的公寓决定了公寓模式?它是线程的公寓还是创建对象的公寓?
考虑以下情形:对象公寓vs线程公寓

  1. 我已经创建了一个只有一个接口,它是ISimpleCom C++ ATL COM DLL,我有一个类,接口,只有一个方法test(); 该类公开农具从设置STA公寓的CComObjectRootEx<CComSingleThreadModel>继承。

  2. 在C#WinForms项目中引用此DLL,并在MTA线程(而不是UI线程)上创建SimpleCom对象。 现在的问题是: 可以说这个对象上的UI线程调用test(),它会被封送到线程创建的对象还是会在UI线程上执行?

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

哪一个是正确的?

回答

2

简单的规则:

  • 线程可能是零或一个公寓成员
  • 单线程公寓(STA)由单个线程的,MTA - 一个或多个线程的,但可以有在每个进程的至多一个MTA
  • 线程在其COM初始化

所以一段代码要么在STA(在STA线程),或在MTA执行,或者t时刻“加入”公寓尚未使用COM初始化hread。当您通过COM实例化一个对象时,COM会将公寓模型与从中调用API的公寓类型相匹配。

此类公开从CComObjectRootEx继承,它设置STA公寓。

不,这与设置公寓模式无关。 CComSingleThreadModel说,这个类是使用简单的基础,这是很好的在STA中运行的对象 - 特别是当它涉及到的访问对象的引用计数,因为假设类为单线程内住它不会使用InterlockedXxx API或关键部分。这确实设置了COM类的公寓模型,它并不表示这个类将在STA上运行,这只是提供了合适的基类。

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

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

... COM将看到它不能直接在调用线程上实例化,因为该线程属于MTA。所以COM将在工作者STA线程上实例化,并将创建一个代理/存根对以将所请求的接口绑定到调用方MTA中。

+0

因此,如果我理解正确,从我在后文中描述的场景中,UI线程和创建类的MTA线程都不会执行test()。 test()的执行会被封送到创建了哪个COM类的工作线程中,并且在哪个线程中? – JobNick

+0

它不会在MTA线程上执行。该调用将被封送到工作人员,或者如果它是STA线程,则将其封装到UI线程中。然后,实际的方法将从那里执行。 –

+0

为了避免混淆,可以使用以下线程:1-UI,2-MTA,3-Worker。所以COM对象是在线程#2上创建的,但因为它是MTA线程,所以它创建了新的线程ID为3的STA工作线程。现在,UI线程#1将调用COM#的对象test()方法,将您的回复test()封送到线程#3并由该线程执行? – JobNick