104

来自关于 STAThread 的 MSDN 文章:

指示应用程序的 COM 线程模型是单线程单元 (STA)。

(仅供参考,这是整篇文章。)

单线程公寓...好吧,这超出了我的想象。另外,我在某处读到,除非您的应用程序使用 COM 互操作,否则此属性实际上什么都不做。那么它究竟做了什么,它又如何影响多线程应用程序呢?多线程应用程序(包括从任何使用Timers 到异步方法调用的任何东西,而不仅仅是线程池等)是否应该使用 MTAThread,即使它“只是为了安全”?STAThread 和 MTAThread 实际上是做什么的?

4

3 回答 3

61

单元线程是一个 COM 概念;如果您不使用 COM,并且您调用的任何 API 都没有“在幕后”使用 COM,那么您无需担心公寓。

如果您确实需要了解公寓,那么细节可能会有点复杂;一个可能过于简化的版本是标记为 STA 的 COM 对象必须在 STAThread 上运行,而标记为 MTA 的 COM 对象必须在 MTA 线程上运行。使用这些规则,COM 可以优化这些不同对象之间的调用,避免不必要的编组。

于 2008-10-03T01:42:26.010 回答
3

它确保CoInitialize将 COINIT_APARTMENTTHREADED 指定为参数。如果您不使用任何 COM 组件或 ActiveX 控件,它对您完全没有影响。如果你这样做,那么它是至关重要的。

单元线程的控件实际上是单线程的,对它们的调用只能在创建它们的单元中处理。

来自 MSDN 的更多细节:

在单线程单元 (STA) 中创建的对象仅从其单元的线程接收方法调用,因此调用被序列化并且仅到达消息队列边界(当调用 Win32 函数 PeekMessage 或 SendMessage 时)。

在多线程单元 (MTA) 中的 COM 线程上创建的对象必须能够随时接收来自其他线程的方法调用。您通常会使用 Win32 同步原语(如临界区、信号量或互斥锁)在多线程对象的代码中实现某种形式的并发控制,以帮助保护对象的数据。

当配置为在中性线程单元 (NTA) 中运行的对象被 STA 或 MTA 中的线程调用时,该线程将传输到 NTA。如果此线程随后调用 CoInitializeEx,则调用失败并返回 RPC_E_CHANGED_MODE。

于 2008-10-03T01:38:32.617 回答
-15

STAThread 在 C# GUI 项目的 Main 函数之前编写。它什么也不做,只是允许程序创建一个线程。

于 2012-03-21T13:48:23.473 回答