zoukankan      html  css  js  c++  java
  • C#的ApartmentState的属性:[STAThread]

    每个Thread都有一个关于ApartmentState的属性,可以把它设置为:STA或者MTA,或者UNKNOWN。
    当你想指定工程的启动窗口的时候,你需要在该窗口类中申明一个Main()方法,并为这个方法设置[STAThread]属性。

    [STAThread]是Single Thread Apartment单线程套间的意思,是一种线程模型,用在程序的入口方法上
    (在C#和VB.NET里是Main()方法),来指定当前线程的ApartmentState 是STA。用在其他方法上不产生影响。
    在aspx页面上可以使用AspCompat = "true" 来达到同样的效果。这个属性只在 Com Interop 有用,
    如果全部是 managed code 则无用。简单的说法:[STAThread]指示应用程序的默认线程模型是单线程单元 (STA)。
    启动线程模型可设置为单线程单元或多线程单元。如果未对其进行设置,则该线程不被初始化。也就是说如果你用的.NET Framework,
    并且没有使用COM Interop,一般不需要这个Attribute。其它的还有MTA(多线程套间)、Free Thread(自由线程)。
    单线程套间,简单来说所有对于单线程套间中对象的访问都是通过消息来传递的,所以同一时间只有一个线程能够访问单线程套间中的对象。

    例如:
    class MainClass
    {
     [STAThread]
    static void Main(string[] args)
    {
     Teacher teacher = new Teacher();
     Student student = new Student();
     student.AdviseDelegateInstance = new Student.AdviseDelegate(teacher.Advise);
     Console.WriteLine("Student got 49");
     student.SetScore(49);
     Console.WriteLine("Student got 87");
     student.SetScore(87);
     Console.ReadLine();
     }
     }

    表示这个Main程序被一个单线程套间包住,且Main的执行,一次只能被一个线程占用,这个线程未执行完,别的线程是没办法调用的。

    http://blog.csdn.net/qilang/archive/2006/06/06/775605.aspx

    STA不是单线程的意思.英文为single threaded apartment.是一种套间(或译为公寓)线程模式.

    sta thread并不表明应用程式的类型,和应用程序不搭界,恰相反,一个应用程序可以有多个线程.每个线程也可以有多个组件或对象.以前win16位系统的组件线程模式才真正是单线程.这是一种被淘汰了的模式.
    线程模式用于处理组件在多线程的环境里并行与并互的方式.比如套间线程(STAThread)模式中接口跨线程传递必须被调度(Marshal),不调度直传肯定会失败!而MTA或FreeThread模式中的接口可以不经调度直接传递.
    这种调度在特定的环境中非常影响性能(可有几百倍之差).如VB里只支持STAThread模式.FreeThread模式的组件会在里面表现成和跨进程一样慢!
    线程模式是微软的COM基础中的极其重要的概念.一定要吃透!
    我对.net真是一窍不通(没空去弄,对不起微软去年的奖赏).但我可以肯定,C#中的[STAThread]属性是应用程序的套间初始化代码.可以直接理解成SDK里的
    CoInitialize(NULL);
    初始一个STA套间实际上是相当于开了一个消息窗口,所有调用经此窗口过程调度到组件内.
    同理[MTAThread](不知有没有这个属性,自已去查)
    可以理解成
    CoInitializeEx(NULL,COINIT_MULTITHREADED )
    这经常是一个对初入com大门的人来说,有一定难度但必须过的一道关.

    打开一个其他人写的C#程序,为了下面的讲解,我把这个程序叫作”DeltaEngine”。DeltaEngine会调用一个本地的程序集,并处理其中某些事件。然后建一个工程,把DeltaEngine作为库项目引用,这个工程又被一个VB程序引用。我把这个VB程序叫做"VBApp"。所以,引用结构就像:

    VBApp (VB) -> DeltaEngine (C#) -> NativeCode

    当我把VBApp作为启动程序运行时,它会一直等待NativeCode里面的事件在DeltaEngine中被处理。我注意到,如果我把DeltaEngine作为启动程序来运行的话,事件就会像预期那样得到处理。我花了很多时间想解决这个问题,但还是很困惑。

    最后有人指出,VB项目的默认线程模型是单线程套间(SingleThreaded Apartment),而C#项目的默认线程模型是多线程套间 (Multithreaded Apartment)。因为DeltaEngine最初是作为C#工程开发的,被默认为使用MTA。当使用VBApp作为启动程序调用DeltaEngine时,DeltaEngine就会使用STA。因为这样,DeltaEngine就会开始等待其实它已经唤起的事件,所以DeltaEngine会一直等待下去。如果我把DeltaEngine作为启动程序运行,它就会使用MTA并且会像预期那样工作。

    解决的方法就是把MTAThreadAttribute加进VBApp的主函数里面。如下:

    <MTAThread> Sub Main()

    类似,如果你想把STAThread attribute加进C#的主方法里面,如下:

    [STAThread]

    static void Main()

    WindowsForms程序要求使用STA,所以创建C# Winapp后,你可以在Program.cs看见像这样的代码。

    我就不重复一些已经有的关于STATread 和MTAThread的文件,所以我给出下面的一些link可以学到更多关于STATread 和MTAThread的东西。

    C# 中WindowsForm 的初始化信息 [STAThread]
    static class Program

    {

    /// <summary>

    /// The main entry point for the application.

    /// </summary>

    [STAThread]

    static void Main()

    {

    Application.EnableVisualStyles();

    Application.SetCompatibleTextRenderingDefault(false);

    Application.Run(new Form1());

    }

    }

    以上的代码是VS 2005中默认的初始化信息.

    Application.EnableVisualStyles();

    简单的说就是让你的控件显示出来.当然是在WindowsForm 中

    此方法为应用程序启用可视样式。如果控件和操作系统支持视觉样式,则控件将以视觉样式进行绘制。若要使 EnableVisualStyles 生效,必须在应用程序中创建任何控件之前调用它;EnableVisualStyles 通常是 Main 函数的第一行.

    下面的代码示例演示如何在 Main 函数中调用 EnableVisualStyles 来启用应用程序的视觉样式

    对于支持 FlatStyle 属性的控件,请确保将 FlatStyle 属性设置为 FlatStyle.System 值。


    using System;

    using System.Drawing;

    using System.Windows.Forms;

    namespace VStyles

    {

    public class Form1 : System.Windows.Forms.Form

    {

    private System.Windows.Forms.Button button1;

    [STAThread]

    static void Main()

    {

    Application.EnableVisualStyles();

    Application.Run(new Form1());

    }

    public Form1()

    {

    this.button1 = new System.Windows.Forms.Button();

    this.button1.Location = new System.Drawing.Point(24, 16);

    this.button1.Size = new System.Drawing.Size(120, 100);

    this.button1.FlatStyle = FlatStyle.System;

    this.button1.Text = "I am themed.";

    // Sets up how the form should be displayed and adds the controls to the form.

    this.ClientSize = new System.Drawing.Size(300, 286);

    this.Controls.Add(this.button1);

    this.Text = "Application.EnableVisualStyles Example";

    }

    }

    }

    由于很多COM在.NET环境下如果使用多线程的话,会导致引用的COM不能正常运行,而如果不声明程序为STAThread的话,.NET就会自动使用多线程来提高效率,这样就会导致不可预知的后果。

  • 相关阅读:
    C#_数据访问类查询 和 属性扩展
    C#_0913 完整修改删除、实体类和数据访问类
    webform基础
    TreeView, 数据导出
    无边框窗体,tiner控件
    容器,打印设置
    多窗体,菜单工具栏
    公共控件
    winform
    数据访问类查询
  • 原文地址:https://www.cnblogs.com/soundcode/p/14591678.html
Copyright © 2011-2022 走看看