gpt4 book ai didi

.net - ApartmentState 傻瓜书

转载 作者:行者123 更新时间:2023-12-03 04:41:18 24 4
gpt4 key购买 nike

我刚刚使用此方法纠正了一个错误:

_Thread.SetApartmentState(ApartmentState.STA);

现在我想了解它的含义以及它为何有效!

最佳答案

COM 是 .NET 的鼻祖。他们对此有相当崇高的目标,COM 所做但 .NET 完全跳过的事情之一是为类提供线程保证。 COM 类可以发布它具有何种线程要求。 COM 基础结构可确保满足这些要求。

这在 .NET 中是完全不存在的。例如,您可以在多个线程中使用 Queue<> 对象,但如果您没有正确锁定,您的代码中将会出现一个很难诊断的严重错误。

COM 线程的具体细节太大,一篇文章无法容纳。我将重点讨论您问题的具体内容。创建 COM 对象的线程必须告诉 COM 它想要为具有受限线程选项的 COM 类提供哪种支持。这些类中的绝大多数仅支持所谓的单元线程,它们的接口(interface)方法只能从创建实例的同一线程安全地调用。换句话说,他们宣布“我不支持任何线程,请注意永远不要从错误的线程调用我”。即使客户端代码实际上确实从另一个线程调用它。

有两种,STA(单线程单元)和MTA。它在 CoInitializeEx() 调用中指定,该函数必须由任何使用 COM 执行任何操作的线程调用。 CLR 每当启动线程时都会自动进行该调用。对于程序的主启动线程,它从 Main() 方法上的 [STAThread] 或 [MTAThread] 属性获取要传递的值。默认为 MTA。对于您自己创建的线程,它由您对 SetApartmentState() 的调用决定。默认为 MTA。线程池线程始终是 MTA,无法更改。

Windows 中有很多代码需要 STA。您自己使用的著名示例是剪贴板、拖放和 shell 对话框(如 OpenFileDialog)。还有很多您看不到的代码,例如 UI 自动化程序和用于观察消息的 Hook 。这些代码都不必是线程安全的,其作者在不知道它在哪个程序中使用的情况下很难使其安全。因此,WPF 或 Windows 窗体项目的 UI 线程必须始终是 STA 才能支持此类代码,创建窗口的任何线程也是如此。

您向 COM promise 您的线程是 STA,但是确实要求您遵循单线程公寓契约。它们非常僵硬,当你违反契约(Contract)时,你可能很难诊断出问题。要求是永远不要阻塞线程任何时间并且泵送消息循环。 WPF 或 Winforms 的 UI 线程可以满足后一个要求,但如果您创建自己的 STA 线程,则需要自己处理。违反契约(Contract)的常见诊断是僵局。

顺便说一句,CLR 内置了相当多的支持来支持这些要求,帮助您避免麻烦。 lock 语句和 WaitOne() 方法在 STA 线程上阻塞时会泵送消息循环。然而,这只能满足永不阻塞的要求,您仍然需要创建自己的消息循环。 WPF 和 Winform 中的 Application.Run()。

我之前贡献过一个答案,其中包含有关使用消息循环来保持 COM 满意的重要性的更多详细信息。您会发现post here .

关于.net - ApartmentState 傻瓜书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4154429/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com