Winforms 需要关于COM与TPL行为的帮助吗

Winforms 需要关于COM与TPL行为的帮助吗,winforms,com,console,task-parallel-library,Winforms,Com,Console,Task Parallel Library,我需要一些帮助来理解STA和MTA在winform和console应用程序方面的区别。我使用第三方COM接口并行执行函数,使用parallel.invoke。当我在控制台应用程序中执行此操作时,一切正常,代码实际上并行运行。但是,当我在Winform中执行相同的操作时,它是按顺序进行的,如果我删除Winform入口点上方的stathread标记,它将开始并行工作。有人能解释这种行为吗?有什么建议就好了 STA和MTA都是COM/ActiveX的“线程模型”,可以追溯到20世纪90年代中期 这里有

我需要一些帮助来理解STA和MTA在winform和console应用程序方面的区别。我使用第三方COM接口并行执行函数,使用parallel.invoke。当我在控制台应用程序中执行此操作时,一切正常,代码实际上并行运行。但是,当我在Winform中执行相同的操作时,它是按顺序进行的,如果我删除Winform入口点上方的stathread标记,它将开始并行工作。有人能解释这种行为吗?有什么建议就好了

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

这里有一个很好的链接:

  • STA:
进程的每个线程都有一个单线程单元(STA) 称为协同初始化。反过来,这些公寓中的每一套都可能没有 一个或多个与之关联的COM对象。顾名思义,, 但是,只有一个特定线程(创建 通过调用CoInitialize)可以直接访问对象 在公寓里

  • MTA:
虽然多线程公寓,有时称为自由线程 公寓,是一种简单得多的模式,它们更难建造 开发,因为开发人员必须实现线程 对象的同步,这绝对是一项不平凡的任务。上 积极的一面是,移除STA的同步机制 开发人员可以更好地控制线程同步的使用。 他们可以将其应用于实际需要的地方,而不是采取行动 非常保守的STA方法,它同步访问 整个公寓

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

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

这里有一个很好的链接:

  • STA:
进程的每个线程都有一个单线程单元(STA) 称为协同初始化。反过来,这些公寓中的每一套都可能没有 一个或多个与之关联的COM对象。顾名思义,, 但是,只有一个特定线程(创建 通过调用CoInitialize)可以直接访问对象 在公寓里

  • MTA:
虽然多线程公寓,有时称为自由线程 公寓,是一种简单得多的模式,它们更难建造 开发,因为开发人员必须实现线程 对象的同步,这绝对是一项不平凡的任务。上 积极的一面是,移除STA的同步机制 开发人员可以更好地控制线程同步的使用。 他们可以将其应用于实际需要的地方,而不是采取行动 非常保守的STA方法,它同步访问 整个公寓


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

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

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

COM必须对MTA线程做些什么,因为它们不适用于线程不安全的COM对象。它创建一个新线程,一个STA线程,为COM对象提供一个安全的家。这是非常低效的,每个方法调用都必须被封送。而且风险很大,如果COM类的对象在内部共享状态,那么它仍然可能是线程不安全的

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

在控制台中,您在MTA线程上创建了它们。因此COM被迫为每个对象创建线程。对工作线程的方法调用仍然被封送,但现在被封送到多个线程。因此,现在您确实获得了并发性,但代价是大量额外的线程。以及服务器内部共享状态时出现故障的风险


通过在工作线程上创建COM对象,使Winforms案例与控制台案例相同。一定要对它进行彻底的测试。

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

要做到这一点