STAThread和多线程

105

来自MSDN关于STAThread的文章:

表示应用程序的COM线程模型是单线程公寓(STA)。

(供参考,那就是整篇文章。)

单线程公寓...好吧,这超出了我的理解范围。另外,我在某个地方读到,除非你的应用程序使用COM互操作,否则这个属性实际上什么也不做。那么它到底是做什么的,它如何影响多线程应用程序?多线程应用程序(包括任何人使用的任何东西,从计时器到异步方法调用,而不仅仅是线程池之类的东西)是否应该使用MTAThread,即使只是“为了安全起见”?STAThread和MTAThread实际上是做什么的?

3个回答

63

公寓线程是一个COM概念;如果您没有使用COM,并且您调用的API中没有使用COM“在内部”,那么您就不需要担心公寓线程。

如果您确实需要了解公寓线程,那么细节可能会变得有点复杂;简化版本是标记为STA的COM对象必须在STAThread上运行,标记为MTA的COM对象必须在MTA线程上运行。按照这些规则,COM可以优化这些不同对象之间的调用,避免在不必要的情况下进行封送。


7
这个说法过于简化了。多线程对象可以在任何线程中运行,而单元线程对象只能在创建它们的单元中运行。 - 1800 INFORMATION
28
来自STA线程的STA对象对MTA对象的调用将被编组到MTA线程上(除非MTA对象实现了free-threaded marshaler)。就像我说的那样,细节可能会变得复杂。(我在COM团队工作了多年 *笑) - Bruce
9
即使您没有直接使用COM,有时也需要注意这一点。如果一个线程显示任何图形窗口,则必须使用单线程公寓模型。这就是为什么在Windows窗体应用程序的主方法顶部始终显示[STAThread]的原因。 - Justin Ethier
6
类似于字体或文件对话框等控件,在你不知道的情况下,是否使用了COM技术?我认为它们在内部可能确实使用了COM技术,这是否意味着几乎所有Windows窗体应用程序都需要设置STAThread?请原谅我的幼稚想法,因为我实际上没有进行过COM编程。 - Brett Ryan
4
如果您有兴趣了解更详细的答案,请访问以下网站:https://dev59.com/J2855IYBdhLWcg3wxHYq(ApartmentState 是线程模型之一,用于控制线程在何时被调度以及如何与其他线程交互。它有两个选项:STA 和 MTA。STA 线程用于单线程的 COM 应用程序,MTA 线程用于多线程的应用程序或不涉及 COM 的应用程序。) - jgauffin
显示剩余3条评论

3
那么它的作用是确保使用 COINIT_APARTMENTTHREADED 作为参数调用 CoInitialize。如果您不使用任何 COM 组件或 ActiveX 控件,则它对您没有任何影响。如果您使用它们,那么它非常关键。
公寓线程化的控件实际上是单线程的,对它们进行的调用只能在创建它们的公寓中处理。
来自 MSDN 的更多详细信息:
“在单线程公寓(STA)中创建的对象仅从其公寓线程接收方法调用,因此调用被序列化并仅在消息队列边界(调用 Win32 函数 PeekMessage 或 SendMessage 时)到达。”
“在多线程公寓(MTA)中的 COM 线程上创建的对象必须能够随时从其他线程接收方法调用。通常会使用 Win32 同步原语(例如临界区、信号量或互斥体)在多线程对象的代码中实现某种形式的并发控制来帮助保护对象的数据。”
“当配置为在中性线程公寓(NTA)中运行的对象由 STA 或 MTA 中的线程调用时,该线程转移到 NTA。如果此线程随后调用 CoInitializeEx,则调用失败并返回 RPC_E_CHANGED_MODE。”

MSDN的文章从COM的角度来看是有帮助的,但你能告诉我.NET何时响应STAThread属性/ApartmentState调用CoInitialize()吗?注意:MSDN上的文章在这里:CoInitializeEx function - jrh
thread->SetApartment 内部是否使用了 CoInitialize()?我一直追踪 STAThread 属性,但是到那里就断了(我找不到 Thread::SetApartment 的源代码)。Thread 类从 thread.h(COM thread.h)中是否有文档记录?它是 MFC、ATL 还是其他什么东西? - jrh
@jrh,抱歉我没有比那更多的细节信息了。 - 1800 INFORMATION

-16

在C# GUI项目的Main函数之前编写STAThread。它不做任何事情,只允许程序创建单个线程。


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