C# 静态线程和多线程

C# 静态线程和多线程,c#,.net,multithreading,sta,C#,.net,Multithreading,Sta,从STAThread上的MSDN文章中: 指示应用程序的COM线程模型为单线程单元(STA) (仅供参考。) 单线程公寓。。。好吧,我想起来了。另外,我在某个地方读到,除非应用程序使用COM互操作,否则该属性实际上什么都不做。那么它到底做什么,以及它如何影响多线程应用程序呢?多线程应用程序(包括使用Timers的任何人到异步方法调用,而不仅仅是线程池等)是否应该使用MTAThread,即使是“为了安全起见”?STAThread和MTAThread实际上做什么?它做什么?它确保调用CoInitia

从STAThread上的MSDN文章中:

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

(仅供参考。)


单线程公寓。。。好吧,我想起来了。另外,我在某个地方读到,除非应用程序使用COM互操作,否则该属性实际上什么都不做。那么它到底做什么,以及它如何影响多线程应用程序呢?多线程应用程序(包括使用
Timer
s的任何人到异步方法调用,而不仅仅是线程池等)是否应该使用MTAThread,即使是“为了安全起见”?STAThread和MTAThread实际上做什么?

它做什么?它确保调用
CoInitialize
,将COINIT\u APARTMENTTHREADED指定为参数。如果不使用任何COM组件或ActiveX控件,则对您没有任何影响。如果你这样做了,那就有点关键了

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

来自MSDN的更多详细信息:

在单线程中创建的对象 公寓(STA)接收方法调用 只是从他们公寓的线索里,所以 调用被序列化并仅到达 在消息队列边界(当 Win32函数消息或 SendMessage被调用)

在中的COM线程上创建的对象 多线程单元(MTA)必须是 能够从接收方法调用 任何时候都可以使用其他线程。你会的 通常实现某种形式的 多线程系统中的并发控制 对象的代码使用Win32 同步原语,例如 关键部分、信号量或 互斥体有助于保护对象的 数据

当一个对象被配置为 在中立的公寓里跑步 (NTA)由中的线程调用 STA或MTA,该线程 转移到NTA。如果这根线 随后调用CoInitializeX 调用失败并返回 RPC_E_已更改_模式


公寓线程是一个COM概念;如果您不使用COM,并且您称之为COM的API中没有一个是“在幕后”使用COM的,那么您就不必担心公寓


如果你真的需要了解公寓,那么细节可以得到;一个可能过于简化的版本是,标记为STA的COM对象必须在STA线程上运行,而标记为MTA的COM对象必须在MTA线程上运行。使用这些规则,COM可以优化这些不同对象之间的调用,避免不必要的封送处理。

STAThread是在C#GUI项目的主功能之前编写的。它只允许程序创建一个线程。

这太简单了。多线程对象可以在任何线程中运行。单元线程化对象只能在创建它们的单元中运行。从STA线程上的STA对象调用MTA对象将封送到MTA线程(除非MTA对象实现自由线程封送器)。就像我说的,细节会变得复杂。(我在COM团队工作了很多年,露齿而笑)有时候你需要意识到这一点,即使你没有直接使用COM。如果线程显示任何图形窗口,则它必须使用单线程单元模型。这就是为什么在windows窗体应用程序中,[StatThread]总是显示在主方法的顶部。字体或文件对话框之类的东西不能在您不知道的情况下使用COM吗?我假设它们是在内部进行的,这是否意味着几乎所有Windows窗体应用程序都需要设置StatThread?请原谅我的naieve假设,因为我实际上没有做过COM编程。对于那些感兴趣的人,有一个更详细的答案:MSDN文章从COM的角度来看很有帮助,但是你能告诉我.NET何时调用
CoInitialize()
来响应
STAThread
属性/
ApartmentState
?注意:关于MSDN的文章如下:。是否在内部使用
CoInitialize()
?我一直在那里跟踪STAThread属性,但是跟踪结果已经变冷了(我找不到
Thread::setpartment
)的源代码)。Thread.h(COM Thread.h)中的Thread类是否记录在任何地方?是MFC、ATL还是其他什么?@jrh我不知道更多的细节,抱歉