1

我需要一些帮助来了解 STA 和 MTA 在 winform 和控制台应用程序方面的区别。我正在使用第三方 COM 接口来并行执行函数,使用 parallel.invoke。当我在控制台应用程序中执行此操作时,一切正常,代码实际上是并行运行的。但是当我在 Winform 中做同样的事情时,它是顺序的,如果我删除 winform 入口点上方的 STAtrhread 标签,它开始并行工作。任何人都可以解释这种行为吗?,任何建议都会很好!

4

2 回答 2

1

COM 有一个在.NET 中完全没有的特性。COM 类可以指定它是否是线程安全的。它使用注册表中名为 ThreadingModel 的键来执行此操作。就像大多数 .NET 类一样,绝大多数 COM 类都不是线程安全的,因此它们指定“Apartment”。这是一个有点晦涩的术语,意味着“只从创建我的线程中调用我”。它自动提供线程安全。

为使其工作,创建 COM 对象的线程必须表明它愿意为非线程安全的 COM 类提供何种支持。STA 线程是安全的家。要求是线程泵送消息循环,就像任何 UI 线程一样。消息循环是 COM 编组从工作线程到创建对象的线程的调用的机制。加入 MTA 的线程明确表示它不提供支持。

COM 必须对 MTA 线程做一些事情,它们不适用于非线程安全的 COM 对象。它创建一个线程,一个 STA 线程,为 COM 对象提供一个安全的家。这非常低效,每个方法调用都必须编组。并且有风险的是,如果 COM 类的对象在内部共享状态,它可能仍然是线程不安全的。

因此,在您的 Winforms 案例中发生的是您在主线程上创建了所有对象,这是一个 STA。并从并行工作线程进行调用,这些调用都被编组并序列化回 STA 线程。不可避免地,它们一个接一个地执行,而您没有并发。

In your Console case, you created them on an MTA thread. So COM is forced to create threads for each object. The method calls on your worker threads are still marshaled, but now to multiple threads. So now you do get concurrency, at the cost of significant overhead, a bunch of extra threads. And the risk of failure when the server shares state internally.

Make the Winforms case the same as the Console case by creating the COM objects on a worker thread. Do test it very thoroughly.

于 2012-07-11T21:16:31.917 回答
0

STA 和 MTA 都是 COM/ActiveX 的“线程模型”,可以追溯到 1990 年代中期。

这是一个很好的链接:

  • STA:

一个进程对于每个调用 CoInitialize 的线程都有一个单线程单元 (STA)。反过来,这些公寓中的每一个都可能有零个或多个与之关联的 COM 对象。然而,顾名思义,只有一个特定线程(通过调用 CoInitialize 创建单元的线程)可以直接访问单元内的对象

  • MTA:

尽管多线程单元(有时称为自由线程单元)是一个更简单的模型,但它们更难开发,因为开发人员必须为对象实现线程同步,这是一项非常重要的任务。从积极的方面来说,删除 STA 的同步机制可以让开发人员更好地控制线程同步的使用。他们可以将其应用到实际需要的地方,而不是采用非常保守的 STA 方法,即同步访问整个公寓。

一个问题是为您的组件选择最佳线程模型(默认为 STA、IIRC)。另一个问题是,如果您需要在组件和使用不同线程模型的组件之间编组数据,运行时会做什么。上面的链接讨论了两者。

于 2012-07-11T19:48:51.510 回答