你能解释STA和MTA吗?

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

另外,什么是公寓线程,只涉及到COM? 如果是这样,为什么?

COM线程模型被称为“公寓”模型,其中初始化的COM对象的执行上下文与单个线程(单线程公寓)或许multithreading(multithreading公寓)相关联。 在这个模型中,COM对象一旦在公寓中初始化,就是在运行期间的一部分。

STA模型用于不是线程安全的COM对象。 这意味着他们不处理他们自己的同步。 这是一个常用的UI组件。 因此,如果另一个线程需要与对象进行交互(例如按下表单中的button),则消息被编组到STA线程中。 Windows窗体消息泵系统就是一个例子。

如果COM对象可以处理自己的同步,那么MTA模型可以用于multithreading被允许与对象进行交互而不用编组调用。

这一切都取决于如何处理对象的呼叫,以及他们需要多less保护。 COM对象可以要求运行时保护它们不被多个线程同时调用; 那些不能从不同的线程同时调用的,所以他们必须保护自己的数据。

此外,如果从用户界面线程进行调用,则运行时还必须防止COM对象调用阻塞用户界面。

公寓是生活对象的地方,它们包含一个或多个线程。 公寓定义了打电话时发生的事情。 除了已经在合适的房间中的线程的呼叫被自己处理(即直接呼叫对象)之外,对公寓中的对象的呼叫将在该房间中的任何线程上被接收和处理。

线程可以在单线程公寓(在这种情况下,它们是该公寓中唯一的线程),也可以在multithreading公寓中。 他们指定哪个线程初始化该线程的COM。

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

相比之下,所有MTA线程共享一个单一的MTA的过程。 如果没有线程可用,COM可能会启动一个新的工作线程来处理一个来电,直到一个池限制。 线程只是阻止外拨电话。

为了简单起见,我们将只考虑在DLL中实现的对象,它们通过在registry中为它们的类的关键字设置ThreadingModel值来在registry中通告它们所支持的内容。 有四个选项:

  • 主线程( ThreadingModel值不存在)。 该对象在主机的主UI线程上创build,所有的调用被编组到该线程。 类工厂将只在该线程上被调用。
  • Apartment 。 这表明该类可以在任何单线程模式线程上运行。 如果创build它的线程是STA线程,则该对象将在该线程上运行,否则将在主STA中创build – 如果没有主STA存在,将为其创buildSTA线程。 (这意味着创buildApartment对象的MTA线程将编组所有对不同线程的调用)。类工厂可以由多个STA线程同时调用,因此它必须保护其内部数据。
  • Free 。 这表明devise在MTA中运行的类。 它将始终在MTA中加载,即使由STA线程创build,这也意味着STA线程的调用将被编组。 这是因为一个Free对象通常会写入,并期望它可以被阻塞。
  • Both 。 这些课程是灵活的,并加载在他们创build的任何公寓。 但是,它们必须写成符合两套要求:它们必须保护其内部状态免受并发呼叫的影响,以防它们在MTA中加载,但不能阻止,以防加载到STA中。

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

我觉得现在的解释太过于粗鲁了。 这是我的简单英文解释:

STA:如果一个线程创build一个设置给STA的COM对象(当调用CoCreateXXX时,你可以传递一个标志来设置COM对象为STA模式),那么只有这个线程才能访问这个COM对象(这就是STA的意思 – 单线程公寓),其他线程试图调用这个COM对象上的方法在引擎盖下默默地变成传递消息到创build(拥有)COM对象的线程。 这非常像只有创buildUI控件的线程才能直接访问它。 而这个机制是为了防止复杂的locking/解锁操作。

MTA:如果一个线程创build一个设置为MTA的COM对象,那么几乎每个线程都可以直接调用它的方法。

这几乎是它的要点。 虽然在技术上有一些我没有提到的细节,比如在“STA”段落中,创build者线程本身必须是STA。 但是,这几乎是所有你必须知道的了解STA / MTA / NA。

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

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

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

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

MTA(multithreading公寓)是许multithreading都可以同时运行的地方,作为开发人员负责处理线程安全。

在COM中有很多要学习线程模型的知识,但是如果你很难理解它们是什么,那么理解STA是什么以及它是如何工作的将是最好的开始,因为大多数的COM对象都是STA的。

公寓线程,如果一个线程和它所使用的对象在同一个房间里,那么它就是一个公寓线程。 我认为这只是一个COM概念,因为它只是讨论它们与之交互的对象和线程的一种方式。

正如我的理解,“公寓”是用来保护COM对象免受multithreading问题。

如果COM对象不是线程安全的,则应该将其声明为STA对象。 那么只有创build它的线程才能访问它。 创build线程应该将自己声明为STA线程。 在线程中,线程将STA信息存储在其TLS(线程本地存储)中。 我们把这种行为称为线程进入STA公寓。 当其他线程想要访问这个COM对象时,它应该编组对创build线程的访问。 基本上,创build线程使用消息机制来处理入站调用。

如果COM对象是线程安全的,则应将其声明为MTA对象。 MTA对象可以被multithreading访问。

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