C#.NET:“多线程单元”和“多线程”

Posted

技术标签:

【中文标题】C#.NET:“多线程单元”和“多线程”【英文标题】:C#.NET: "Multi Threaded Apartment" and "Multithreading" 【发布时间】:2016-12-19 07:27:59 【问题描述】:

我正在学习多线程概念(通常是针对 C#.NET)。阅读不同的文章,仍然无法完全理解一些基本概念。

我发布this 问题。 “Hans Passant”很好地解释了它,但我无法理解它的某些部分。所以我开始用谷歌搜索。

我阅读了this 没有答案的问题。

多线程和 MTA 是一样的吗?

假设我编写了一个 STA 的 WinForm 应用程序(如上所述它的 Main() 方法),我仍然可以在我的应用程序中创建多个线程。我可以肯定地说我的应用程序是“多线程的”。这是否也意味着我的申请是 MTA?

在谈论 STA/MTA 时,大多数文章(如 this)都在谈论 COM/DCOM/Automation/ActiveX。这是否意味着 DotNet 与 STA/MTA 无关?

【问题讨论】:

【参考方案1】:

没有。 MTA 是单线程的属性,就像 STA 一样。你现在做出完全相反的承诺,你声明线程绝对什么来保证外部代码线程安全。因此,无需调度员,您可以尽可能多地阻止。

这当然会产生后果,而且可能会非常令人不快。如果您的程序的 UI 线程在 MTA 中,那将是致命的,因为它使用了许多从根本上说是线程不安全的外部组件。剪贴板不起作用,拖放不起作用,OpenFileDialog 通常只会挂起您的程序,WebBrowser 不会触发其事件。

某些组件会对此进行检查并引发异常,但此检查并未始终如一地实施。 WPF 值得注意,虽然单元状态通常只对非托管代码很重要,但 WPF 借用了这个概念并提出了“调用线程必须是 STA,因为许多 UI 组件都需要这个”。这有点误导,它的真正含义是线程必须有一个调度程序才能允许其控件工作。但在其他方面与 STA 承诺一致。

当组件使用COM并且作者提供了代理时,它可以工作。 COM 基础结构现在介入以使组件线程安全,它创建一个新线程,即 STA,为它提供一个安全的家。并且每个方法调用都会自动编组,因此它在该线程上运行,从而提供线程安全。与 Dispatcher.Invoke() 完全等效,但完全自动完成。然而,结果是这很慢,通常需要几纳秒的简单属性访问现在可能需要几微秒。

如果该组件支持 MTA 和 STA,您将很幸运。这并不常见,只有像微软这样的公司才会付出更多的努力来保持他们的库线程安全。

我或许应该强调,.NET Framework 中完全没有公寓的概念。除了说明公寓类型的基础知识之外,这是必要的,因为 .NET 程序通常需要与非托管代码进行互操作。所以用工作线程编写一个 Winforms 应用程序就可以了,这些工作线程总是在 MTA 中,但是你可以自己处理线程安全,没有什么是自动的。

这通常很好理解,几乎每个人都知道如何使用 lock 关键字、Task 和 BackgroundWorker 类,并且知道从工作线程更新 UI 需要 Control.Begin/Invoke() 方法。使用 InvalidOperationException 来提醒您出错时。把它留给程序员而不是系统来处理线程安全确实使使用线程变得更加困难。但是给了你很多比系统做得更好的机会。这是必要的,这种系统提供的线程安全在 90 年代后期的中间件战争中被 Java 打脸时遭到了严重的黑眼圈。

【讨论】:

【参考方案2】:

有一些问题,但首先让我们从这个开始:

Apartment 是 COM 对象被初始化和执行的上下文,它可以是单线程 (STA),通常用于非线程安全对象,也可以是多线程。

术语公寓,它描述了 COM 所在的结构 对象被创建

发件人:https://msdn.microsoft.com/en-us/library/ms809971.aspx

所以Multithreading和MTA是不一样的,但是MTA是Multithreaded。 我们可以说STA 和MTA 都与COM 对象相关。 你可以在这里阅读更多:https://msdn.microsoft.com/en-us/library/ms693344(v=vs.85).aspx

所以,对于您的第二个问题,如果您的 WinForm 应用程序是“多线程的”并不意味着它是“MTA”。

最后,MTA/STA 概念比 .Net 技术更早,但我们不能说它们没有任何关系,因为 .Net 在 STA 和 MTA 中都支持 COM 技术。

我希望我的回答能帮助您理解单元和线程之间的区别。

更多有趣的阅读在这里:Could you explain STA and MTA?

【讨论】:

以上是关于C#.NET:“多线程单元”和“多线程”的主要内容,如果未能解决你的问题,请参考以下文章

Linux下C/C++ 手写一个线程池-

Linux C 实现一个简单的线程池

JAVA线程池shutdown和shutdownNow的区别

ADO多线程数据库查询

多线程公寓的目的是什么?

线程池