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

阿米特·乔希

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

我发布这个问题。“汉斯·帕桑(Hans Passant)”很好地解释了这一点,但我无法理解其中的一部分。所以我开始谷歌搜索。

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

多线程和MTA是否相同?

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

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

汉斯·帕桑特

不能。MTA是单线程的属性,就像STA一样。现在,您做出完全相反的承诺,声明该线程绝对不执行任何操作来保持外部代码的线程安全。因此,无需派遣人员,您就可以根据需要阻止任意多长时间。

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

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

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

如果该组件支持MTA和STA,那么您会很幸运。这是不常见的,只有像Microsoft这样的人花了额外的时间才能保持其库的线程安全性。

我也许应该强调,.NET Framework中完全没有公寓的概念。除了说明单元类型的基础知识外,这是必需的,因为.NET程序通常需要与非托管代码互操作。因此,使用工作线程编写Winforms应用程序就可以了,这些工作线程始终在MTA中,但是您确实需要自己处理线程安全问题,并且没有自动的方法。

通常,这很容易理解,几乎每个人都知道如何使用lock关键字Task和Background类,并且知道需要使用Control.Begin / Invoke()方法从工作线程更新UI。使用InvalidOperationException可以在错误时提醒您。由程序员而不是由系统负责线程安全的问题确实使使用线程变得更加困难。但是给您提供了很多比系统更好的机会。必要的是,在90年代后期的中间件战争期间,当Java将其猛击时,这种系统提供的线程安全性遭到了严重的关注。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章