2

我已经阅读了很多有关 Microsoft 的线程单元模型的信息,但我仍然在可视化它时遇到了一些麻烦。

微软使用住在公寓里的生物进行类比。因此,对于 STA,请考虑以下内容(我知道这有点傻)。

  1. 假设线程 = 人,COMObject = 细菌。人住在公寓里,细菌住在人体内。因此在 STA-Land 中,线程存在于 STA 中,而 COMObject 存在于线程中,因此为了与 COMObject 交互,必须通过在 COMObject 的线程上运行代码来实现。

  2. 假设线程 = 人,COMObject = 猫。人住在公寓里,猫和人住在公寓里。SO在STA-Land中,线程和COMObject处于同一层次。

Q1。上面哪个类比是正确的,或者如果都不正确,您将如何描述 STA?

Q2。您如何描述 MTA?

4

2 回答 2

3

我不喜欢这些类比。他们令人困惑。

你创建一个公寓。

如果是 STA,则单元中只有一个线程,因此该单元中的所有对象都将在该单个线程上执行(因此该单元中的对象没有并发执行)

如果它是 MTA,则该单元中可以有多个线程。因此,如果需要,MTA 中的对象需要显式地实现同步。

一个对象住在一个公寓里。同一个公寓里可以有多个对象。

一个很好的阅读here

于 2012-01-26T07:09:23.830 回答
3

这不是一个很好的术语。它实际上描述了线程行为。一个线程告诉 COM 它在 CoInitializeEx() 调用中的行为方式,在 STA 和 MTA 之间进行选择。通过使用 STA,线程承诺它的行为方式适合非线程安全的代码。它做出的坚定承诺是:

  • 从不阻止执行
  • 泵送消息循环

使用 MTA 意味着线程可以做它想做的任何事情,并且不会做出任何努力来支持非线程安全的代码。

当创建 COM 对象时,这首先很重要。这样的对象在注册表中包含一个键,该键描述了它实现了哪种线程安全。ThreadingModel 键。到目前为止,该键最常见的值是“Apartment”(或缺失),它告诉 COM 它根本不支持线程,并且对对象的任何调用都必须从同一个线程进行。

如果创建这样一个对象的线程在 STA 中,那么一切都很顺利。毕竟,线程承诺支持单线程对象。如果线程在 MTA 中,那么就有问题,线程说它不支持线程安全,但仍然创建了一个不是线程安全的对象。COM 步骤创建一个线程,一个可以支持非线程安全代码的 STA 线程。代码获取对象的代理。对该对象进行的任何调用都会通过该代理。代理代码拦截调用并使其在创建的 STA 线程上运行,从而确保以线程安全的方式进行调用。

可以想象,代理完成的工作并不便宜。它涉及两个线程上下文切换,并且必须从函数参数构造一个堆栈帧才能进行调用。它还必须等到线程准备好执行调用。这被称为marshaling,它比进行不需要编组的调用要慢 3 个数量级。这也许也解释了 STA 线程具有上面列出的这两个要求的原因。它不能阻塞,因为只要它阻塞了无法进行封送调用并很可能导致死锁。它必须泵送一个消息循环,该循环使得将调用注入另一个线程成为可能。

因此,使线程加入 MTA 对您来说很容易编程。但对性能致命。STA 是有效的。

于 2012-01-26T11:14:43.717 回答