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

时间:2011-01-11 15:25:08

标签: c# .net winforms sta

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

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

我真的有一些问题:

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

4 个答案:

答案 0 :(得分:19)

引用an MSDN blog

  

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

答案 1 :(得分:12)

  

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

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

  

2。这是什么意思?

这意味着该线程在single-threaded apartment model

中运行
  

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

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

答案 2 :(得分:3)

  

3.如果删除此属性会怎么样?

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

我使用按钮和OpenFileDialog创建了简单的WinForms应用程序。单击按钮,我运行一个显示openFileDialog的线程。我使用和不使用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已停止工作"

答案 3 :(得分:0)

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