STAThread 初學習集合

http://blog.sina.com.cn/s/blog_4493d3b50100u6vi.html

[STAThread]--Single-Thread Apartment

 

在C#中用在Main()函數之前,指定當前線程的ApartmentState是STA,用在其他方法上沒有作用。

有時根據設計需要,需要同COM進程進行交互,例如使用Windows clipboard。

以下引用另一同輩的發言: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#學習筆記(一)-- 入門的困惑
簡單的我就不寫了,主要寫一下C#學習中的要點和難點。


1.由HelloWorld開始
先看一段基本上每本C#書裏都會講到的例子,很老土。

using System;
namespace test
{
     class Class1
     {
         [STAThread]
         static void Main(string[] args)
         {
              System.Console.WriteLine("Hello,World!");
         }
     }
}


先引用一個命名空間System,再定義一個自己的命名空間test,裏面有一個類Class1,屬性[STAThread],一個入口的Main方法,注意:跟JAVA不一樣,Main首名母是大寫,Main必須是static的。不然怎麼開始呢?難倒要實例化才行?哈哈,定義爲static就是把它放在椎裏。這裏規舉。
 
2.命名空間
再來看看System.Console.WriteLine("Hello,World!");輸一名語名到控制檯。調用System命名空間裏的Console類的WriteLine方法。System命名空間是前面我們已經引用了的using System;
 
你也可以在引用的時候改個名字output,那麼在調用的時候就是output.Console.WriteLine("Hello,World!");
試一試:
using output=System;
 
namespace test
{
     class Class1
     {
         [STAThread]
         static void Main(string[] args)
         {
              output.Console.WriteLine("Hello,World!");
         }
     }
}

運行報錯:F:\mydoc\Visual Studio Projects\test\Class1.cs(7): 找不到類型或命名空間名稱“STAThread”(是否缺少 using 指令或程序集引用?)
嘿嘿,是[STAThread]惹的禍。幹掉它。再試,搞定。
[STAThread]是Single  Thread  Apartment單線程套間的意思。是一種線程模型。其它的好像還是MTA(多線程套間)、Free  Thread(自由線程)。這個屬性要加在主  Main  上。這個屬性只在  Com  Interop 所用,如果全部是  managed  code  則無用。簡單的說法:[STAThread]指示應用程序的默認線程模型是單線程單元 (STA)。啓動線程模型可設置爲單線程單元或多線程單元。如果未對其進行設置,則該線程不被初始化。
也就是說如果你用的.NET Framework,並且沒有使用COM Interop,一般不需要這個Attribute。
 
明白了吧。
 
注意,using指令是用於命名空間的。變化着用一下,也可以爲類創建別名:
using output=System.Console;
 
namespace test
{
     class Class1
     {
         //[STAThread]
         static void Main(string[] args)
         {
              output.WriteLine("Hello,World!");
         }
     }
}

這樣也行。。。
 
命令空間是可以嵌套的。如:
using System;
 
namespace test
{
     namespace t1
     {
         class Class1
         {
              static void Main(string[] args)
              {
                   System.Console.WriteLine("t1.Class1");
              }
         }
     }
 
     namespace t2
     {
         class Class2
         {
              static void Main(string[] args)
              {
                   System.Console.WriteLine("t2.Class2");
              }
         }
     }
}

運行,報錯。我是故意的(臺下:大騙子)。J不要扔磚頭啊。不要這麼容易就放棄嘛,要執着。
看錯誤F:\mydoc\Visual Studio Projects\test\Class1.cs(9): 程序“F:\mydoc\Visual Studio Projects\test\obj\Debug\test.exe”定義了不止一個入口點:“test.t1.Class1.Main(string[])”
 
因爲你的命名空間test裏定義了二個Main方法,所以呢,不用我說了吧。
using System;
 
namespace test
{
     namespace t1
     {
         class Class1
         {
              static void Main(string[] args)
              {
                   System.Console.WriteLine("t1.Class1");
                   System.Console.WriteLine(t2.Class2.MyFunction());
              }
         }
     }
 
     namespace t2
     {
         class Class2
         {
              public static string MyFunction()
              {
                   return "t2.Class2";
              }
         }
     }
}

外部程序引用的時候就是這樣:using test.t1;或using test.t2;
 
入門就這些問題。
打開Visual Studio .NET 2003 命令提示鍵入ILDASM,這個程序可以查看編譯後的元數據。
 
網上查一下Reflector這個軟件。幹什麼用的。反編譯呀。。。。寒。
=========================================================================


單線程套間(STAThread) vs. 多線程套間(MTAThread )
[原文鏈接]:  STA Thread vs. MTAThread(WHost)

 

      最近我遇到一個有趣的線程問題,想跟大家分享一下,以免大家也遇到這種容易混淆的問題。

      打開一個其他人寫的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的東西。

     STAThreadAttribute

      http://msdn2.microsoft.com/en-us/library/system.stathreadattribute(VS.71).aspx                           http://blogs.msdn.com/jfoscoding/archive/2005/04/07/406341.aspx

     MTAThreadAttribute

      http://msdn2.microsoft.com/en-us/library/system.mtathreadattribute(VS.71).aspx

======================================================================================
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";
 
        }
    }
}



發佈了58 篇原創文章 · 獲贊 102 · 訪問量 67萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章