Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 对象公寓vs线程公寓_C#_C++_Com_Atl - Fatal编程技术网

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线程调用此

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

> p>我创建了C++的ATL COM DLL,它只有一个接口,即代码> ISPysECOM < /代码>,并且我有一个类,该接口只有一个方法<代码>测试()代码> 此类公开继承自设置STA单元的
CComObjectRootEx

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

    • 如果它跟随对象COM单元,则应将此调用封送到创建该对象的线程,因为它是STA对象
    • 如果它是在创建线程单元(MTA)之后执行的,那么它应该在UI线程上执行
  • 哪一个是正确的?

    简单规则:

    • 线程可能是零个或一个单元的成员
    • 单线程单元(STA)由一个或多个线程组成的单线程MTA组成,但每个进程最多只能有一个MTA
    • 线程在COM初始化时“加入”单元
    因此,一段代码要么在STA(在STA线程上)中执行,要么在MTA中执行,或者线程尚未用COM初始化。当您通过COM实例化对象时,COM将使单元模型与调用API的单元类型相匹配

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

    不,这与设置公寓模型无关
    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。“两者”是公寓线程模型。另一方面,对象可以嵌入“自由线程封送处理程序”,这是一种特殊类型的封送处理实现,它以原始形式在单元之间传递接口指针,从而消除代理。也许这就是你的意思。