English 中文(简体)
你能解释一下STA和MTA吗?
原标题:
  • 时间:2008-09-24 13:40:23
  •  标签:

你能用自己的话解释STA和MTA吗?

此外,什么是单元线程?它们是否只与COM有关?如果是,为什么?

最佳回答

COM线程模型称为“单元”模型,其中初始化的COM对象的执行上下文与单个线程(单线程单元)或多个线程(多线程单元)相关联。在这个模型中,COM对象在单元中初始化后,在其运行时是该单元的一部分。

STA模型用于非线程安全的COM对象。这意味着它们不处理自己的同步。它的一个常见用途是UI组件。因此,如果另一个线程需要与对象交互(例如按下表单中的按钮),那么消息将被整理到STA线程上。windows窗体消息抽取系统就是一个例子。

如果COM对象可以处理自己的同步,那么可以使用MTA模型,其中允许多个线程与对象交互,而无需整理调用。

问题回答

这一切都取决于如何处理对对象的调用,以及它们需要多少保护。COM对象可以要求运行时保护它们不被多个线程同时调用;那些没有的线程可能会从不同的线程并发调用,因此它们必须保护自己的数据。

此外,如果从用户接口线程进行调用,则运行时也有必要防止COM对象调用阻塞用户接口。

公寓是对象居住的地方,它们包含一个或多个线程。公寓定义了打电话时会发生什么。对单元中对象的调用将在该单元中的任何线程上接收和处理,但已经在正确单元中的线程的调用由其自身处理(即对对象的直接调用)除外。

线程可以在单线程单元中(在这种情况下,它们是该单元中唯一的线程),也可以在多线程单元中。它们指定线程在初始化该线程的COM时使用哪个。

STA主要是为了与绑定到特定线程的用户界面兼容。STA通过接收到隐藏窗口的窗口消息来接收要处理的呼叫的通知;当它进行出站调用时,它会启动一个模式消息循环,以防止其他窗口消息被处理。您可以指定要调用的消息筛选器,以便应用程序可以响应其他消息。

相比之下,所有MTA线程都为进程共享一个MTA。如果没有可用的线程,COM可能会启动一个新的工作线程来处理传入调用,最高可达池限制。进行出站调用的线程只是阻塞。

为了简单起见,我们将只考虑在DLL中实现的对象,这些对象通过为其类的键设置ThreadingModel值,在注册表中公布它们所支持的内容。有四种选择:

  • Main thread (ThreadingModel value not present). The object is created on the host s main UI thread, and all calls are marshalled to that thread. The class factory will only be called on that thread.
  • Apartment. This indicates that the class can run on any single-threaded-mode thread. If the thread that creates it is an STA thread, the object will run on that thread, otherwise it will be created in the main STA - if no main STA exists, an STA thread will be created for it. (This means MTA threads that create Apartment objects will be marshalling all calls to a different thread.) The class factory can be called concurrently by multiple STA threads so it must protect its internal data against this.
  • Free. This indicates a class designed to run in the MTA. It will always load in the MTA, even if created by an STA thread, which again means the STA thread s calls will be marshalled. This is because a Free object is generally written with the expectation that it can block.
  • Both. These classes are flexible and load in whichever apartment they re created from. They must be written to fit both sets of requirements, however: they must protect their internal state against concurrent calls, in case they re loaded in the MTA, but must not block, in case they re loaded in an STA.

从.NET Framework中,基本上只需在任何创建UI的线程上使用[STAThread]。工作线程应该使用MTA,除非它们要使用Apartment标记的COM组件,在这种情况下,如果从多个线程调用同一个组件,则使用STA来避免编组开销和可扩展性问题(因为每个线程都必须依次等待该组件)。如果每个线程使用一个单独的COM对象,无论组件是在STA还是MTA中,这都会容易得多。

我觉得现有的解释过于官样文章。以下是我用通俗易懂的英语解释:

STA: If a thread creates a COM object that s set to STA (when calling CoCreateXXX you can pass a flag that sets the COM object to STA mode), then only this thread can access this COM object (that s what STA means - Single Threaded Apartment), other thread trying to call methods on this COM object is under the hood silently turned into delivering messages to the thread that creates(owns) the COM object. This is very much like the fact that only the thread that created a UI control can access it directly. And this mechanism is meant to prevent complicated lock/unlock operations.

MTA: If a thread creates a COM object that s set to MTA, then pretty much every thread can directly call methods on it.

这几乎就是它的要点。虽然从技术上讲,有些细节我没有提到,比如在STA段落中,但创建者线程本身必须是STA。但要理解STA/MTA/NA,你几乎只需要知道这些。

STA(单线程单元)基本上是这样一个概念,即一次只有一个线程与您的代码交互。通过windows消息(使用不可见的)窗口封送对您公寓的呼叫。这允许对调用进行排队并等待操作完成。

MTA(Multi-Threaded Apartment,多线程公寓)是许多线程可以同时运行的地方,作为开发人员,您有责任处理线程安全性。

关于COM中的线程模型还有很多需要学习的地方,但如果你很难理解它们是什么,那么我想说,理解STA是什么以及它是如何工作的将是最好的起点,因为大多数COM对象都是STA的。

单元线程,如果一个线程与它正在使用的对象住在同一个单元中,那么它就是一个单元线程。我认为这只是COM的一个概念,因为这只是谈论与之交互的对象和线程的一种方式…

承载COM或OLE控件的每个EXE都定义其单元状态。公寓状态默认为STA(对于大多数程序,应该为STA)。

STA-所有OLE控件必须存在于STA中。STA意味着必须始终在UI线程上操作COM对象,并且不能将其传递给其他线程(很像MFC中的任何UI元素)。但是,您的程序仍然可以有许多线程。

MTA-您可以在程序中的任何线程上操作COM对象。

据我所知,Apartment用于保护COM对象免受多线程问题的影响。

如果COM对象不是线程安全的,它应该将其声明为STA对象。然后只有创建它的线程才能访问它。创建线程应该将自己声明为STA线程。在引擎盖下,线程将STA信息存储在其TLS(线程本地存储)中。我们将这种行为称为线程进入STA单元。当其他线程想要访问此COM对象时,它应该封送对创建线程的访问。基本上,创建线程使用消息机制来处理绑定调用。

如果COM对象是线程安全的,它应该将其声明为MTA对象。MTA对象可以由多线程访问。

调用COM对象dll(例如,读取专有数据文件)的代码在用户界面中可能工作正常,但在服务中神秘地挂起。原因是,从.Net 2.0开始,用户界面采用STA(线程安全),而服务采用MTA(在此之前,服务采用STA)。必须为服务中的每个COM调用创建一个STA线程可能会增加大量开销。

本文解释了STA&;MTA非常清楚。

Understanding COM Apartments, Part I
Understanding COM Apartments, Part II

关于公寓的要点:

  • An apartment is a concurrency boundary; it’s an imaginary box drawn around objects and client threads that separates COM clients and COM objects that have incompatible threading characteristics.
  • Every thread that uses COM, and every object that those threads create, is assigned to an apartment.
  • When a thread calls COM’s CoInitialize or CoInitializeEx function, that thread is placed in an apartment. And when an object is created, it too is placed in an apartment.
  • Whenever it creates a new apartment, COM allocates an apartment object on the heap and initializes it with important information such as the apartment ID and apartment type. When it assigns a thread to an apartment, COM records the address of the corresponding apartment object in thread-local storage (TLS).

附带说明:如果您正在使用某些PowerShell 2.0管理单元,则需要启动带有-MTA选项的PowerShell版本3或更高版本才能使用它们。PowerShell 2单元模型是MTA,而更高版本使用STA作为默认值。另一点是吝啬。公寓中的普通呼叫没有编组(直接呼叫),所以如果您的呼叫方是x64,那么被呼叫方也必须是x64。唯一的解决方法是使用远程过程调用(RPC),这会增加大量的开销(通过某种方式生成一个新的32位进程来加载管理单元DLL和查询结果)。对于开发人员来说:始终发布类型库-这会使COM对象的发现和使用更加容易!每个接口都应该是公共的和唯一的——实现可以是专有的,也可以是开源的。

另一种情况

例子:

 IStorage_vtbl** reference; // you got it by some means of factory
 
 
 public unsafe int OpenStorage(char* pwcsName, IStorage pstgPriority, uint grfMode, char** snbExclude, uint reserved, IStorage* ppstg)
 {
     IStorage_vtbl** @this = (IStorage_vtbl**)reference;
     IStorage_vtbl* vtbl = *@this;
     if (vtbl == null)
         throw new InvalidComObjectException();
     Delegate genericDelegate = Marshal.GetDelegateForFunctionPointer(vtbl->method_6, typeof(delegate_6));
     delegate_6 method = (delegate_6)genericDelegate;
     return method(@this, pwcsName, pstgPriority, grfMode, snbExclude, reserved, ppstg);
 }
 

This fragment of code just add this pointer of instance for real call to COM subsystem So, is this call to open instance of IStorage STA or MTA?





相关问题
热门标签