Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 线程公寓状态_C#_Multithreading - Fatal编程技术网

C# 线程公寓状态

C# 线程公寓状态,c#,multithreading,C#,Multithreading,全部, 我在C#中使用线程已经有一段时间了,但对于线程的单元状态到底意味着什么,我仍然有点困惑。我知道WinForms必须始终使用STA公寓状态(与MTA相反),但我仍然不清楚公寓状态的含义 这篇由Raymond Chen撰写的关于新旧事物的博文介绍了STA和MTA线程模型背后的一些历史: […]COM培养了两种性格,一种是 专注于GUI客户和 另一个关注点是非GUI 客户。对于非GUI客户, 其他功能,如 增加了多线程公寓, 因为客户没有做GUI 多线程公寓 没有GUI规则的负担。 他们没有给

全部,


我在C#中使用线程已经有一段时间了,但对于线程的单元状态到底意味着什么,我仍然有点困惑。我知道WinForms必须始终使用STA公寓状态(与MTA相反),但我仍然不清楚公寓状态的含义

这篇由Raymond Chen撰写的关于新旧事物的博文介绍了STA和MTA线程模型背后的一些历史:

[…]COM培养了两种性格,一种是 专注于GUI客户和 另一个关注点是非GUI 客户。对于非GUI客户, 其他功能,如 增加了多线程公寓, 因为客户没有做GUI 多线程公寓 没有GUI规则的负担。 他们没有给我发信息 相互沟通;他们用 内核对象和 WaitForSingleObject。人人都赢, 对吧?

是的,每个人都赢了,但是你 你必须知道你的面包是哪一面 奉承。如果初始化GUI 线程作为多线程单元, 你违反了假设 多线程公寓在哪 我们是被发明的![……]


COM有着非常崇高的目标。其中之一是线程是一个编程细节,很难正确处理,应该由支持库管理。与.NET非常不同,在.NET中,完全由您以线程安全的方式使用非线程安全的类

这是通过注册表实现的,COM类发布ThreadingModel注册表项,该注册表项说明它支持哪种线程。到目前为止,它们中的大多数使用“单元”,这是一种有点不清楚的表示“我不支持多线程”的方式。这是COM确保以线程安全的方式调用所有方法的信号。如果您的程序从工作线程调用一个方法,那么COM负责将工作线程的调用封送到创建实例的线程。从而自动确保以线程安全的方式使用服务器。与Control.Invoke和Dispatcher.Invoke的工作方式不同,但完全是自动的

这当然是一个奇妙的魔法,但是你的程序确实需要一些合作。如果没有您的帮助,COM无法封送这样的调用。当您的程序创建线程时,它必须调用CoInitialize()来告诉COM基础结构您希望参与COM调用。那时,你必须告诉它你创建了什么样的线程。有两种,以“公寓”类型区分。有STA(单线程单元)和MTA(多线程单元)。STA线程是一个友好的COM组件,不支持线程。MTA线程不可用

不过,这种公寓有一个价格标签。创建STA时,必须遵循STA规则。这有点苛刻:

  • 您必须启动Windows消息循环
  • 你永远不能阻止线程
消息循环是COM将调用从一个线程封送到另一个线程的机制。需要使用从不阻塞规则来防止死锁。虽然是龙的,但它是程序的UI线程的工作方式。这不是巧合

在MTA线程上创建公寓线程COM对象时,还会附加一个价格标签。这样的线程不是一个好的家,它不遵循STA规则。COM没有帮助,无法封送方法调用。COM介入并实际创建自己的STA线程,为对象提供一个好客的家。很好,但不便宜,因为这会消耗线程,并且每个方法调用都被封送,这会给每个调用增加很多开销

COM线程支持非常好,它在98%的时间里处理所有事情,而不需要做任何特殊的事情。然而,2%的偏头痛会给你带来巨大的偏头痛,你能做的很少。它的伸缩性也很差,这可能是.NET没有类似功能的最大原因


虽然COM可能看起来已经死了,但公寓在Windows编程中仍然是一件大事。NET框架对它们有明确的支持。在STA线程上调用Thread.Join()或Monitor.Enter(),例如,通过COM显式地verboten,使CLR泵成为一个消息循环。其他工件是您在GUI应用程序的Main()方法上看到的[STAThread]属性和Thread.SetApartmentState(),这是以正确方式获取CLR调用CoInitialize()的方法。剪贴板、拖放和shell对话框(如OpenFileDialog)等GUI功能明确要求STA工作。创建任何窗口的线程都应该始终是STA线程。

不过……这两种模型之间有什么区别?也许举个例子?@koumides-除了更改入口点上的属性(
[STAThread]
vs
[MTAThread]
)外,C代码没有太大区别。UI线程必须是STA。如果你弄错了,你可能会观察到车辆行为、碰撞、死锁等。我真的不知道你在寻找什么样的例子。如果你直接使用WinF32编码(不使用WinFrm(使用C、C++或C p/pUnk调用),那么,是的,将会有不同。@ KouMIDES——总之,C语言中的开发,我不太了解细节,也不需要知道。有关您的问题的可能更好的答案,请参阅。可能的副本包括: