使用Visual Studio创建空的WinForms应用程序模板时,主应用程序类中会有STAThread
属性。
我阅读了一些相关文档,但我不确定是否完全理解它。
实际上,我有一些问题:
- 为什么会添加这个属性?
- 它是什么意思?
- 如果删除此属性会发生什么?
使用Visual Studio创建空的WinForms应用程序模板时,主应用程序类中会有STAThread
属性。
我阅读了一些相关文档,但我不确定是否完全理解它。
实际上,我有一些问题:
引用自MSDN博客,
当应用 STAThreadAttribute 属性时,它会将当前线程的公寓状态更改为单线程。不详细讨论COM和线程问题,此属性确保当前线程与可能通过COM想要与之通信的其他线程之间的通信机制。当您使用Windows Forms时,根据您使用的功能,它可能需要使用COM互操作来与操作系统组件进行通信。好的例子是剪贴板和文件对话框。
1. 为什么要添加这个属性?
因为它是ActiveX对象模型所需的。您可以在WinForm上放置ActiveX控件(因此它存在于兼容性方面),或者一些.NET类使用需要该属性的本机控件。
2. 它是什么意思?
它表示线程在单线程公寓模型中运行。
3. 如果删除此属性会发生什么?
如果删除属性,则行为未定义。程序可能会随机失败,并且有时会显示合理的错误消息。例如,现在可能正常工作,但在服务包中会出现问题。
3. 如果您删除此属性会发生什么?
我添加了一个简单的示例来演示这个问题。
我创建了一个简单的WinForms应用程序,其中包含一个按钮和一个OpenFileDialog。在按钮点击时,我运行一个线程来显示openFileDialog。我使用STAThread和不使用STAThread启动应用程序,点击按钮的结果是相同的 - 它抛出异常“跨线程操作无效:从创建它的线程以外的线程访问控件'Form1'。” 看起来没有区别。但其实是有区别的。
然后我通过调用下面的方法来改变显示openFileDialog:
private void ShowOFD()
{
if (InvokeRequired)
{
BeginInvoke(new Action(ShowOFD));
return;
}
openFileDialog1.ShowDialog(this);
}
使用STAThread时,它按预期正常工作。没有STAThread时,会抛出异常:“在进行OLE调用之前,必须将当前线程设置为单线程公寓(STA)模式。确保您的Main函数已标记STAThreadAttribute。只有在调试器连接到进程时才会引发此异常。”
然后我多次启动应用程序而没有调试器(从Visual Studio分离)。有一次应用程序悄无声息地关闭,另一次应用程序带有“vshost已停止工作”的消息而关闭。
这意味着Windows Forms程序使用单线程公寓状态。MTA和自由线程公寓状态不受支持。