为什么默认情况下WinForms应用程序是STAThread?

使用Visual Studio创建空WinForms应用程序时,模板在主应用程序类中具有STAThread属性。

我一直在阅读一些关于它的文档,但我不确定我是否理解它。

我真的有一些问题:

  1. 为什么要添加此属性?
  2. 这是什么意思?
  3. 如果删除此属性会发生什么?

1.为什么要添加此属性?

因为它是ActiveX对象模型所必需的。 并且您可以在WinForm上删除ActiveX控件(因此它是为了兼容性)或者某些.NET类使用需要该属性的本机控件。

这是什么意思?

这意味着该线程在单线程单元模型中运行 。

3.如果删除此属性会发生什么?

如果删除该属性,则行为未定义。 程序可能会随机失败,有时会出现明显的错误消息。 例如,现在可能会有效,然后打破服务包。

引用MSDN博客 ,

应用STAThreadAttribute时,它会将当前线程的单元状态更改为单线程。 在没有深入讨论COM和线程的情况下,这个属性确保了当前线程和其他线程之间的通信机制,这些线程可能希望通过COM与它通信。 当您使用Windows窗体时,根据您使用的function,它可能正在使用COM互操作以与操作系统组件进行通信。 这方面的好例子是剪贴板和文件对话框。

3.如果删除此属性会发生什么?

我只是添加一个演示问题的简单示例。

我用一个按钮和一个OpenFileDialog创建了简单的WinForms应用程序。 单击按钮,我运行一个显示openFileDialog的线程。 我使用和不使用STAThread启动应用程序,单击按钮的结果是相同的 – 它会抛出exception“跨线程操作无效:控制’Form1’从其创建的线程以外的线程访问”。 看起来好像没有区别。 但不是。

然后我通过调用下面的方法更改了显示openFileDialog:

 private void ShowOFD() { if (InvokeRequired) { BeginInvoke(new Action(ShowOFD)); return; } openFileDialog1.ShowDialog(this); } 

使用STAThread,它可以正常工作。 如果没有STAThread,则抛出exception:“在进行OLE调用之前,必须将当前线程设置为单线程单元(STA)模式。确保Main函数上标记了STAThreadAttribute。仅在连接调试器时引发此exception过程“。

然后我在没有调试器的情况下多次启动应用程序(与visual studio分离)。 有一次应用程序只是默默地关闭,另一次应用程序关闭,消息“vshost已停止工作”

这意味着Windows窗体程序使用单线程单元状态。 不支持MTA和自由线程单元状态。