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
表示這個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#的ApartmentState的属性:[STAThread]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 账户数贷款其他1是什么意思
- 下一篇: 银行对公业务是什么