正如MSDN指出:
如果你正在写一个单线程应用程序(或一个多线程的应用程序,其中只有一个线程在同一时间访问一个DOM),使用租赁线程模型(Msxml2.DOMDocument.3.0或Msxml2.DOMDocument.6.0)。 如果你正在写多个线程访问将同时访问DOM的应用程序,使用免费的线程模型(Msxml2.FreeThreadedDOMDocument.3.0或Msxml2.FreeThreadedDOMDocument.6.0)。
有FreeThreadedDOMDocument,中性公寓和自由线程编组之间有联系吗? 我看着在OLEVIEW,发现FreeThreadedDOMDocument线程模型两种。 据我了解中立公寓对象与自由线程编组支持。 这是否意味着FreeThreadedDOMDocument不使用自由线程编组,它被称为一个有点混乱,作为自由线程?
那是什么标记为免费,这两种或中性COM类之间的差别实现? 据我了解,他们都必须是线程安全的,为什么不一样? 难道纠正中性应该支持自由线程编组?
这里有多种问题。
TL; DR:
中性的对象:
- 招致在进程编组比STA和MTA对象少一点
- 避免线程切换
- 接口指针自动编组
- 中性的公寓住,只要有一个中立的对象活着
- 必须准备好任何线程下运行 ,使用COM实用功能等待或选择的Win32等待功能取决于螺纹类型使用
自由线程的对象:
- 招致几乎没有进程封送处理
- 避免线程切换
- 接口指针不会自动封
- 寿命是联系在一起的激活公寓
- 必须准备好任何线程下运行 ,使用COM实用功能等待或选择的Win32等待功能取决于螺纹类型使用
有FreeThreadedDOMDocument,中性公寓和自由线程编组之间有联系吗?
TL; DR:该FreeThreadedDOMDocument
的线程模型是‘两者’,所以它绑在那里的激活公寓(创建)。 它聚集了自由线程封送,所以它是一个自由线程对象。
该FreeThreadedDOMDocument
是一个COM类,它的对象聚集自由线程封送 。 这有什么不封送是提供原始指针每当编组进程(即IMarshal::MarshalInterface
与dwDestContext
设置为MSHCTX_INPROC
。
我将使用一个自由线程对象的定义为,其聚合的自由螺纹封送的对象。
一个自由的线程对象的线程模型应该被指定为“中性”或“两者” Windows 2000之前,因此它可以创建在任何线程中使用,避免了上下文切换。
如果它的线程模型被指定为“两者”,对象的生存是依赖于在创建它的公寓。 举例来说,如果一个STA线程终止时,该公寓中创建的所有自由线程对象被销毁或不再有效。
据我了解中立公寓对象与自由线程编组支持。
不,代理中性对象比其他进程代理打火机一点,因为它只是建立了一个COM背景,但在全编组从未招致它可以避免线程切换。
这是否意味着FreeThreadedDOMDocument不使用自由线程编组,它被称为一个有点混乱,作为自由线程?
不, FreeThreadedDOMDocument
不使用自由线程封送。
在历史上, 已经有自由线程对象之前,微软为他们提供了自己的支持(由于人气,可能是因为最自由线程封送拆出有片状),和中性的公寓只出现在Windows 2000。
因此,实例FreeThreadedDOMDocument
是自由线程,因为它们聚集自由线程编组和每个实例的生命周期被绑定到创建它的公寓。 通常情况下,几乎没有影响,但与STA线程例如线程池,效果观察更多的时候,因为STA的来来去去,所属线程终止(正常或回收资源),并获得创建。 例如,传统的ASP默认使用STA线程。
PS:我已经提到了以下几个主题另一个答案 ,但我相信内容是有点不同,因为问题也不同。
下面是当前线程模型值:
- 无:使用主STA
- “公寓”:使用任何STA,即如果当前的公寓是STA或NA在STA,使用当前的STA,否则使用主机 STA(后面会更多)
- “自由”:使用MTA
- “两者”:使用当前公寓
- “中性”:用NA
对于不存在任何的公寓,如果需要的话COM创建它。
这里有几个特点:
- 使用主STA,你一定不要提任何线程模型,而不是更多的东西明智的,如“主”
- 除“中性”的所有名称并没有什么意义时下:
- “公寓”感觉就像目前的公寓 ,但它不是
- “自由”感觉就像自由线程对象 ,但它不是
- “无论是”让你觉得只有2个公寓类型,但有3个:STA,MTA和NA
- 实际上,由于Windows 8中,有ASTA,即用于GUI其中,年内拨出电话,丢弃来电创建STA的变化不相关 ,从而避免重入错误的重要来源
- 你可以做一个定期STA这样的表现与消息过滤器
主要STA是创建的第一个STA。 唯一要紧的与未指定的线程模型类。
可以有多个STA,但最多有一个MTA和一个NA。
虽然有一个活跃的MTA,对于COM未初始化任何线程是隐含在MTA如果不调用CoInitializeEx(NULL, COINIT_MULTITHREADED)
但它也完全不影响MTA的生命周期,这意味着MTA可能被破坏而线程使用它。 由于这是很少记载和非常不可靠的,你不应该依赖于这一点。
隐式创建的公寓被称为主机STA和主机MTA 。 你必须在他们身上没有控制(除非作弊CoUninitialize
而在该公寓;注意:不要真正做到这一点)。 事实上,如果你激活STA之外或外部的NA运行在一个STA的“公寓”的对象,它会在宿主STA激活。 对于进一步的混乱,这也可能是主STA如果主机STA是第一STA被初始化。
支持主机公寓所有的COM线程后台线程,这样他们就不会从退出让你的应用程序。
你有没有任何控制权的NA,比激活中性对象时创建它的其他。 你不能直接进入它,但你可以运行在中性公寓的背景下,回调的方法创建自己的中性对象。 这种回调可能是一个自由线程对象。
那是什么标记为免费,这两种或中性COM类之间的差别实现?
以声明为“自由”公寓COM类将导致属于MTA对象。 此类物品可能会认为他们在运行线程不必泵窗口消息。 从本质上讲,他们可能会阻止。
自由线程对象和中性对象必须做好准备, 在任何运行公寓 。 对于自由线程对象,它应该是显而易见的原因是:它绕过任何上下文封送处理,所以方法的任何线程中执行。 对于中性的对象,有区别的是哪种公寓是活跃的 (通过CoGetApartmentType
)。
在任一情况下,应该使用COM的效用函数,如CoWaitForMultipleHandles
代替WaitForMultipleHandles
[
Ex
]
,这些块和是不可接受的的STA,或MsgWaitForMultipleHandles
[
Ex
]
,它访问窗口的消息队列,可能创造它隐含,并且通常是不能接受的在MTA的。
你可以自己去查公寓类型,并选择使用正确的Win32等待功能,或者使用与在STA超时等待和泵消息的轮询策略,如果你正在等待比处理其他事情,或者如果您需要具体等待逻辑。
自由螺纹对象和中性对象之间的最显着的差异被编组其它COM对象。
当使用中性目的,传入和传出接口指针被自动编组。 例如,你可以存储领域进入的接口指针。
在使用自由线程对象,传入和传出接口指针不封可言,这意味着无论你到物体原始指针在同一所公寓,或者你代理在其他公寓的对象。 这些代理是绑在当前的公寓了。
例如,进入的原始指针意味着你得到属于当前公寓的对象,所以你必须元帅,如果要存储的对象的引用。
传入代理意味着你要代理到另一个房间的对象,但这种代理是依赖于当前的公寓。 你也不能存储此代理。 具体而言,尽管标准的代理/存根公寓验证,STA的代理可以具有螺纹的亲和力。 你必须封送它。 不过不用担心,编组的代理不会叠加编组; 当你再次解组,你会得到一个代理对象,而不是代理到代理。
当一个自由线程对象必须存储的接口指针,它必须总是通过手动编组这样做,当它必须调用从该接口的指针的方法,它必须通过手动解编这样做。
通常情况下, 全局接口表 (GIT;另一种误导名称,它实际上是一个进程表)被用于此目的。
据我了解,他们都必须是线程安全的,为什么不一样?
关于线程安全的,没有区别。
但正如我在上一个问题解释说,有存储接口指针时的巨大差异,以及有关对象激活和寿命微妙的差别。
难道纠正中性应该支持自由线程编组?
自由线程编组有效地忽略了公寓,所以它的方法有责任的行为,同步和/或正确锁紧。 所以,无论是公寓必须支持自由线程封送,这是自由线程对象必须支持所有的公寓。
这有可能聚集在物体的自由线程封送任何线程模型,包括“中性”。
如果您发现由中立公寓封送的上下文设置是某种瓶颈,那么你可以考虑使用自由线程编组在手动编组存储接口指针的成本。 如果没有,只是用中性的公寓。