FreeThreadedDOMDocument,中立公寓和自由线程的封锁 [英] FreeThreadedDOMDocument, Neutral Apartments and Free-Threaded Marshaler

查看:339
本文介绍了FreeThreadedDOMDocument,中立公寓和自由线程的封锁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如MSDN所示:


如果您正在编写一个单线程应用程序DOM),使用租赁线程模型(Msxml2.DOMDocument.3.0或Msxml2.DOMDocument.6.0)。如果您正在编写一个应用程序,其中多个线程访问将同时访问DOM,请使用免费线程模型(Msxml2.FreeThreadedDOMDocument.3.0或Msxml2.FreeThreadedDOMDocument.6.0)。


FreeThreadedDOMDocument,中性公寓和免费线程封送器之间是否有任何连接?我在OleView中查找并发现FreeThreadedDOMDocument线程模型是Both。据我所知,中性的公寓对象是用自由螺纹的封送器支持的。是否意味着FreeThreadedDOMDocument不使用自由线程的封送器,它被称为有点混乱的自由线程?



COM类之间的实现差异是什么标记为免费,两者还是中性?据我所知,他们都必须是线程安全的,为什么有区别?

解决方案

这里有多个问题。



TL; DR:



中性物件:




  • 减少 封锁比STA和MTA物件

  • 避免线程切换

  • 介面指针 .microsoft.com / en-us / library / windows / desktop / ms692663(v = vs.85).aspxrel =nofollow>在任何类型的线程下运行,使用COM实用函数等待或根据线程类型选择Win32等待函数



自由线程对象:


$ b $


  • 界面指针自动编组

  • 生命周期与激活公寓相关

  • 必须准备好在任何类型的线程下运行,使用COM实用程序函数,用于根据线程类型等待或选择Win32等待函数使用





  • TL; DR: FreeThreadedDOMDocument code>的线程模型是Both,所以它绑定到它被激活(创建)的公寓。



    FreeThreadedDOMDocument 是一个COM类,它的对象请聚合免费线程封送者此封锁者的作用是提供一个原始指针,每当封送进程(即 IMarshal :: MarshalInterface dwDestContext 设置为 MSHCTX_INPROC



    我将使用一个自由线程对象的定义作为聚合免费线程化封送器的对象。



    在Windows 2000之前,一个自由线程对象的线程模型应该被指定为Neutral或Both,所以它可以在任何线程中创建和使用,避免上下文切换。



    如果它的线程模型被指定为Both,对象的生命周期被绑定到它被创建的公寓。例如,如果一个STA线程终止,在那个公寓内创建的所有自由线程对象被销毁或者不再有效。


    根据我的理解,中立的公寓对象支持一个自由线程的封送。


    不,对中性对象的代理比其他进程代理稍微轻一点,因为它只设置一个COM上下文,它从不会导致完全封送,并避免线程切换。


    这意味着FreeThreadedDOMDocument不使用自由线程封送


    不, FreeThreadedDOMDocument



    历史上,已经有免费的线程对象之前微软提供了自己的支持他们(由于受欢迎程度,也许是因为大多数免费线程封送器出现片状),中立公寓只出现在Windows 2000。 / p>

    因此, FreeThreadedDOMDocument 的实例是免费的线程,因为它们聚合了空闲线程封送器和每个实例的生命周期被绑在它被创造的公寓。通常,没有什么影响,但使用例如。一个线程池的STA线程,效果被观察更频繁,因为STA来来去,因为拥有线程终止(正常或回收资源)并创建。例如,经典的ASP默认使用STA线程。



    PS:我在另一个答案,但我相信内容有点不同,因为问题也不同。



    这里是当前的线程模型值:




    • 无:使用主STA

    • 公寓:使用任何STA当前公寓是在STA上的STA或NA,使用当前STA,否则使用主机 STA(稍后详述)。

    • Free MTA

    • 两者:使用当前公寓

    • 中性:使用NA

    • <

      对于任何不存在的公寓,COM会根据需要创建它。



      这里有几个特点:




      • 要使用主STA,您不必提及任何线程模型,而不要提供更明智的内容,例如Main

      • 除了Neutral之外的所有名字现在都没有意义:


        • 公寓感觉像当前公寓它不是

        • 免费感觉像免费的线程对象,但不是

        • 只有2个公寓类型,但有3个:STA,MTA和NA


          • 实际上,从Windows 8开始,有ASTA对于GUI,在去电期间,丢弃来电不相关,因此避免了重入错误的重大来源

          • 您可以使一个常规STA的行为像这样与消息过滤器





      主STA是第一个创建的STA。



      可以有多个STA,但最多只能有一个MTA和一个NA。



      虽然有一个活动的MTA,如果没有调用 CoInitializeEx(NULL,COINIT_MULTITHREADED),但它也不影响MTA的生命周期,这意味着MTA可能会在线程使用它时被销毁。由于这些文件很少,并且几乎不可靠,因此您不应该依赖此。



      隐式创建的公寓称为主机STA和主机MTA 。你不能控制他们(除非在那个公寓里用 CoUninitialize 作弊;注意:实际上不这样做)。实际上,如果激活在STA之外或在通过STA运行的NA之外的公寓对象,则它将在主机STA中被激活。



      所有支持主机公寓的COM线程都是后台线程,因此,如果主机STA是第一个被初始化的STA,它们不会阻止您的应用程序退出。



      除了在激活中性对象时创建它外,您对NA没有任何控制。您不能直接输入它,但是您可以使用在中性公寓环境中运行回调的方法创建自己的中性对象。这个回调可以是一个自由的线程对象。


      COM类之间的实现区别是什么,标记为Free,Both或Neutral? p>

      COM类与公寓声明为Free将导致属于MTA的对象。这样的对象可以假定它们运行的​​线程不必泵送窗口消息。基本上,它们可能会阻止。



      自由线程对象和中性对象必须准备在任何公寓下运行。对于免费的线程对象,它应该是明显的为什么:它绕过任何上下文封送,所以方法在任何线程执行。对于中性对象,有哪种类型的公寓处于活动状态(通过 CoGetApartmentType )。



      无论哪种情况,都应该使用COM的效用函数,如 CoWaitForMultipleHandles ,而不是 WaitForMultipleHandles [ Ex ] ,阻止和不接受在STA,或 MsgWaitForMultipleHandles [ Ex ] ,它访问窗口消息队列,可能隐式创建它,并且在MTA中通常是不可接受的。



      您可以自己检查公寓类型,并选择使用正确的Win32等待功能,或者使用轮询策略,等待和泵送消息在STA中的超时,以防您等待除句柄以外的东西如果你需要一个特定的等待逻辑。



      自由线程对象和中性对象之间最明显的区别是其他COM对象的编组。



      使用中性对象时,传入和传出接口指针将自动编组。例如,您可以将传入接口指针存储在字段中。



      在使用自由线程对象时,传入和传出接口指针 ,意味着你得到原始指针到同一公寓中的对象,或者你得到代理到其他公寓的对象。这些代理绑定到当前的公寓。



      例如,一个传入的原始指针意味着你得到一个属于当前公寓的对象,如果您打算存储对对象的引用,则必须编组。



      传入代理意味着您正在获取另一个公寓中的对象的代理,但此代理被绑在当前的公寓。您也不能存储此代理。具体来说,尽管标准代理/存根的公寓验证,STA代理可以具有线程亲和性。你必须编组它。但不要担心,封送代理将不会堆栈封送;当你再次解组时,你将获得对象的代理,而不是代理的代理。



      当一个自由的线程对象必须存储一个接口指针时,总是通过手动编组来实现,当它必须通过这个接口指针调用方法时,必须通过手动解包来实现。



      通常,全局接口表(GIT;另一个误导性名称,它实际上是一个正在进行中的表)用于这个目的。


      据我所知,他们都必须是线程安全的,为什么有区别?


      关于线程安全,没有区别。 b

      但是正如我在前面的问题中解释的那样,存储接口指针时有很大的区别,对于对象激活和生命周期的细微差别。


      Neutral是否应该支持一个自由线程的封送者?


      免费的线程封送器公寓,所以它的方法的责任行为,同步和/或锁定正确。因此,两个公寓都不得支持免费的线程化封送器,它是必须支持每个公寓的自由线程对象。



      可以通过任何线程聚合对象中的免费线程封送器模型,包括中性。



      如果您发现中性公寓封店的上下文设置是某种瓶颈,那么您可以考虑使用免费的线程封送手动编排存储的接口指针的成本。如果没有,只需使用中性公寓。


      As MSDN states:

      If you are writing a single threaded application (or a multi-threaded application where only one thread accesses a DOM at one time), use the rental threaded model (Msxml2.DOMDocument.3.0 or Msxml2.DOMDocument.6.0). If you are writing an application where multiple threads access will simultaneously access a DOM, use the free threaded model (Msxml2.FreeThreadedDOMDocument.3.0 or Msxml2.FreeThreadedDOMDocument.6.0).

      Is there any connection between FreeThreadedDOMDocument, neutral apartments and free-threaded marshaler? I looked in OleView and found that FreeThreadedDOMDocument threading model is Both. As far as I understand neutral apartment objects are supported with a free-threaded marshaler. Does it mean that FreeThreadedDOMDocument doesn't use a free-threaded marshaler and it is called a bit confusing as free-threaded?

      What is the implementation difference between COM classes that marked as Free, Both or Neutral? As far as I understand they all must be thread-safe, why is the difference? Is it correct that Neutral should support a free-threaded marshaler?

      解决方案

      There are multiple questions here.

      TL;DR:

      Neutral objects:

      • Incur a bit less in-process marshaling than STA and MTA object
      • Avoid thread switching
      • Interface pointers are automatically marshaled
      • Neutral apartment lives as long as there's a neutral object alive
      • Must be ready to run under any kind of thread, using COM utility functions for waiting or choosing the Win32 wait function to use depending on the thread type

      Free threaded objects:

      • Incur practically no in-process marshaling
      • Avoid thread switching
      • Interface pointers are not automatically marshaled
      • Lifetime is tied to the activation apartment
      • Must be ready to run under any kind of thread, using COM utility functions for waiting or choosing the Win32 wait function to use depending on the thread type

      Is there any connection between FreeThreadedDOMDocument, neutral apartments and free-threaded marshaler?

      TL;DR: The FreeThreadedDOMDocument's threading model is "Both", so it's tied to the apartment where it's activated (created). It aggregates the free threaded marshaler, so it's a free threaded object.

      The FreeThreadedDOMDocument is a COM class whose objects aggregate the free threaded marshaler. What this marshaler does is to provide a raw pointer whenever marshaling in-process (i.e. IMarshal::MarshalInterface with dwDestContext set to MSHCTX_INPROC.

      I'll use definition of a free threaded object as an object which aggregates the free threaded marshaler.

      A free threaded object's threading model should be specified as "Neutral", or "Both" before Windows 2000, so it can be created and used in any thread, avoiding context switches.

      If its threading model is specified as "Both", the object's lifetime is tied to the apartment where it was created. For instance, if an STA thread terminates, all free threaded objects created within that apartment are either destroyed or no longer valid.

      As far as I understand neutral apartment objects are supported with a free-threaded marshaler.

      No, proxies to neutral objects are a bit lighter than other in-process proxies as it only sets up a COM context, but it never incurs in full marshaling and it avoids thread switching.

      Does it mean that FreeThreadedDOMDocument doesn't use a free-threaded marshaler and it is called a bit confusing as free-threaded?

      No, the FreeThreadedDOMDocument does use the free threaded marshaler.

      Historically, there were already free threaded objects before Microsoft provided its own support for them (due to popularity, and probably because most free threaded marshalers out there were flaky), and the Neutral apartment appeared only in Windows 2000.

      As such, instances of FreeThreadedDOMDocument are free threaded because they aggregate the free threaded marshaler, and the lifetime of each instance is tied to the apartment where it was created. Usually, there's little impact, but with e.g. a thread-pool of STA threads, the effect is observed more often, because STAs come and go as the owning threads terminate (either normally or to reclaim resources) and get created. For instance, classic ASP uses STA threads by default.

      PS: I've mentioned the following subject in another answer, but I believe the content is a bit different as the questions are different too.

      Here's the current threading model values:

      • None: use the main STA
      • "Apartment": use any STA, i.e. if the current apartment is STA or NA over STA, use the current STA, otherwise use the host STA (more on this later)
      • "Free": use the MTA
      • "Both": use the current apartment
      • "Neutral": use the NA

      For any apartment that doesn't exist, COM creates it if needed.

      There are several peculiarities here:

      • To use the main STA, you must not mention any threading model, instead of something more sensible, like "Main"
      • All names except "Neutral" make no sense nowadays:
        • "Apartment" feels like the current apartment, but it's not
        • "Free" feels like free threaded objects, but it's not
        • "Both" makes you think there are only 2 apartment types, but there are 3: STA, MTA and NA
          • Actually, since Windows 8, there's ASTA, a variation of STA that is created for the GUI which, during outgoing calls, discards incoming calls that are not related, thus avoiding a great source of reentrancy bugs
          • You can make a regular STA behave like this with a message filter

      The main STA is the first created STA. It only matters for classes with an unspecified threading model.

      There can be several STAs, but there are at most one MTA and one NA.

      While there is an active MTA, any thread not initialized for COM is implicitly in the MTA if it doesn't call CoInitializeEx(NULL, COINIT_MULTITHREADED), but it also doesn't affect the MTA's lifetime at all, meaning the MTA may be destroyed while the thread is using it. Since this is scarcely documented and pretty much unreliable, you shouldn't rely on this.

      Implicitly created apartments are called host STA and host MTA. You have no control over them (unless by cheating with CoUninitialize while in that apartment; note: don't actually do this). In fact, if you activate "Apartment" objects outside of an STA or outside of an NA running over an STA, it'll be activated in a host STA. For further confusion, this might also be the main STA if the host STA was the first STA to be initialized.

      All COM threads that support host apartments are background threads, so they don't keep your application from exiting.

      You have no control whatsoever over the NA, other than creating it when activating a neutral object. You cannot enter it directly, but you can create your own neutral object with a method that runs a callback in the context of the neutral apartment. This callback could be a free threaded object.

      What is the implementation difference between COM classes that marked as Free, Both or Neutral?

      COM classes with apartment declared as "Free" will result in objects that belong to the MTA. Such objects may assume that the threads they run in don't have to pump window messages. Essentially, they may block.

      Free threaded objects and neutral objects must be prepared to run under any apartment. For free threaded objects, it should be obvious why: it bypasses any context marshaling, so methods execute in any thread. For neutral objects, there's the distinction of which kind of apartment was active (through CoGetApartmentType).

      In either case, you should use COM's utility functions, like CoWaitForMultipleHandles instead of WaitForMultipleHandles[Ex], which blocks and is unacceptable in STAs, or MsgWaitForMultipleHandles[Ex], which accesses the window message queue, probably creating it implicitly, and is usually unacceptable in MTAs.

      You can check the apartment type by yourself and choose to use the proper Win32 waiting functions or to use a polling strategy which waits and pumps messages with timeouts in the STA, in case you're waiting on something other than handles or if you require a specific waiting logic.

      The most striking difference between free threaded objects and neutral objects is marshaling of other COM objects.

      While using neutral objects, incoming and outgoing interface pointers are automatically marshaled. For instance, you can store incoming interface pointers in fields.

      While using free threaded objects, incoming and outgoing interface pointers are not marshaled at all, meaning either you get raw pointers to objects in the same apartment, or you get proxies to objects in other apartments. These proxies are tied to the current apartment too.

      For instance, an incoming raw pointer means you're getting an object that belongs to the current apartment, so you'll have to marshal it if you intend to store a reference to the object.

      An incoming proxy means you're getting a proxy to an object in another apartment, but this proxy is tied to the current apartment. You can't store this proxy either. Specifically, notwithstanding standard proxy/stubs' apartment verification, STA proxies may have thread affinity. You must marshal it as well. But don't worry, marshaling a proxy will not stack marshaling; when you again unmarshal, you'll get a proxy to the object, not a proxy to a proxy.

      When a free threaded object must store an interface pointer, it must always do so through manual marshaling, and when it must call methods from this interface pointer, it must do so through manually unmarshaling.

      Usually, the Global Interface Table (GIT; another misleading name, it's actually an in-process table) is used for this purpose.

      As far as I understand they all must be thread-safe, why is the difference?

      Regarding thread-safety, there's no difference.

      But as I explained in the previous question, there's a huge difference when storing interface pointers, and a subtle difference regarding object activation and lifetime.

      Is it correct that Neutral should support a free-threaded marshaler?

      The free threaded marshaler effectively ignores the apartment, so it's the methods' responsibility to behave, synchronize and/or lock correctly. So, neither apartment must support the free threaded marshaler, it's the free threaded object that must support every apartment.

      It's possible to aggregate the free threaded marshaler in objects with any threading model, including "Neutral".

      If you find that the context setup by the neutral apartment marshaler is somehow a bottleneck, then you may consider using the free threaded marshaler, at the cost of manually marshaling stored interface pointers. If not, just use the neutral apartment.

      这篇关于FreeThreadedDOMDocument,中立公寓和自由线程的封锁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆