C#.NET: "多线程公寓"和"多线程"

6

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

我发布了这个问题。 "Hans Passant" 解释得很好,但我无法理解其中的一些部分。所以我开始谷歌搜索。

我读过这个没有答案的问题。

多线程和MTA是相同的吗?

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

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

2个回答

9
不,MTA是单线程的属性,就像STA一样。你现在做出了完全相反的承诺,声明该线程绝对不会保持外部代码的线程安全。因此,没有必要使用调度程序,您可以阻塞尽可能长的时间。
当然,这会产生后果,而且可能非常不愉快。如果您的程序的UI线程处于MTA状态,那么它将使用许多基本上不安全的线程外组件。剪贴板无法工作,拖放不起作用,打开文件对话框通常会使您的程序挂起,WebBrowser不会触发其事件。
某些组件会检查并引发异常,但此检查未得到一致实施。WPF值得注意,虽然公寓状态通常只与非托管代码有关,但WPF借用了这个概念并引发了“调用线程必须为STA,因为许多UI组件需要此。”这有点误导人,它真正意味着线程必须有一个调度程序来允许其控件工作。但与STA承诺一致。
当组件使用COM并且作者提供了代理时,它可以工作。 COM基础设施现在介入以使组件线程安全,它创建一个新线程,该线程是STA以给它一个安全的家。每个方法调用都会自动进行编组,因此在该线程上运行,从而提供线程安全性。完全等同于Dispatcher.Invoke()但完全自动完成。然而,后果是这很慢,通常只需要几纳秒的简单属性访问现在可能需要多个微秒。
如果组件支持MTA和STA,则您会很幸运。这不常见,只有像Microsoft这样的人才会走额外的千里路来保持其库的线程安全。
我或许应该强调一下,公寓的概念在.NET Framework中完全缺失。除了基本的声明公寓类型之外,这是必要的,因为.NET程序经常需要与非托管代码交互。因此,使用工作线程编写Winforms应用程序非常好,这些工作线程始终在MTA中,但是您必须自己处理线程安全性,而且没有任何自动化。
这通常是众所周知的,几乎每个人都知道如何使用lock关键字,Task和BackgroundWorker类,并知道Control.Begin/Invoke()方法是从工作线程更新UI所需的。当您犯错时,它会提醒您InvalidOperationException。将线程安全性留给程序员而不是系统来处理确实使使用线程更加困难。但是,这给了您比系统更好的机会。这是必要的,当Java在90年代后期的中间件战争中打击它时,这种由系统提供的线程安全性受到了严重的打击。

1

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

一个公寓是初始化和执行COM对象的上下文,它可以是单线程(STA),通常用于不支持多线程的对象,也可以是多线程。

术语公寓描述了创建COM对象的结构

来自:https://msdn.microsoft.com/en-us/library/ms809971.aspx

因此,多线程和MTA不是相同的,但MTA是多线程的。 我们可以说 STA和MTA与COM对象相关。 您可以在此处阅读更多信息:https://msdn.microsoft.com/en-us/library/ms693344(v=vs.85).aspx

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

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

我希望我的答案能帮助您了解公寓和线程之间的区别。

这里有更有趣的阅读材料:你能解释一下STA和MTA吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接