下面我們就動手來建立一個執行緒,使用Thread類建立執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒幹什麼事)
在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的,你可以把ThreadStart理解為一個函式指標,指向執行緒要執行的函式,當呼叫Thread.Start()方法後,執行緒就開始執行ThreadStart所代表或者說指向的函式。
開啟你的VS.net,新建一個控制檯應用程式(Console Application),編寫完全控制一個執行緒的程式碼示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
//ThreadTest.cs using System; using System.Threading; namespace ThreadTest { public class Alpha { public void Beta() { while (true) { Console.WriteLine("Alpha.Beta is running in its own thread."); } } }; public class Simple { public static int Main() { Console.WriteLine("Thread Start/Stop/Join Sample"); Alpha oAlpha = new Alpha(); file://這裡建立一個執行緒,使之執行Alpha類的Beta()方法 Thread oThread = new Thread(new ThreadStart(oAlpha.Beta)); oThread.Start(); while (!oThread.IsAlive) Thread.Sleep(1); oThread.Abort(); oThread.Join(); Console.WriteLine(); Console.WriteLine("Alpha.Beta has finished"); try { Console.WriteLine("Try to restart the Alpha.Beta thread"); oThread.Start(); } catch (ThreadStateException) { Console.Write("ThreadStateException trying to restart Alpha.Beta. "); Console.WriteLine("Expected since aborted threads cannot be restarted."); Console.ReadLine(); } return 0; } } } |
這段程式包含兩個類Alpha和Simple,在建立執行緒oThread時我們用指向Alpha.Beta()方法的初始化了ThreadStart代理(delegate)物件,當我們建立的執行緒oThread呼叫oThread.Start()方法啟動時,實際上程式執行的是Alpha.Beta()方法:
1 2 3 |
Alpha oAlpha = new Alpha(); Thread oThread = new Thread(new ThreadStart(oAlpha.Beta)); oThread.Start(); |
然後在Main()函式的while迴圈中,我們使用靜態方法Thread.Sleep()讓主執行緒停了1ms,這段時間CPU轉向執行執行緒oThread。然後我們試圖用Thread.Abort()方法終止執行緒oThread,注意後面的oThread.Join(),Thread.Join()方法使主執行緒等待,直到oThread執行緒結束。你可以給Thread.Join()方法指定一個int型的引數作為等待的最長時間。之後,我們試圖用Thread.Start()方法重新啟動執行緒oThread,但是顯然Abort()方法帶來的後果是不可恢復的終止執行緒,所以最後程式會丟擲ThreadStateException異常。
主執行緒Main()函式
所有執行緒都是依附於Main()函式所在的執行緒的,Main()函式是C#程式的入口,起始執行緒可以稱之為主執行緒。
如果所有的前臺執行緒都停止了,那麼主執行緒可以終止,而所有的後臺執行緒都將無條件終止。
所有的執行緒雖然在微觀上是序列執行的,但是在巨集觀上你完全可以認為它們在並行執行。
Thread.ThreadState 屬性
這個屬性代表了執行緒執行時狀態,在不同的情況下有不同的值,我們有時候可以通過對該值的判斷來設計程式流程。
ThreadState 屬性的取值如下:
- Aborted:執行緒已停止;
- AbortRequested:執行緒的Thread.Abort()方法已被呼叫,但是執行緒還未停止;
- Background:執行緒在後臺執行,與屬性Thread.IsBackground有關;
- Running:執行緒正在正常執行;
- Stopped:執行緒已經被停止;
- StopRequested:執行緒正在被要求停止;
- Suspended:執行緒已經被掛起(此狀態下,可以通過呼叫Resume()方法重新執行);
- SuspendRequested:執行緒正在要求被掛起,但是未來得及響應;
- Unstarted:未呼叫Thread.Start()開始執行緒的執行;
- WaitSleepJoin:執行緒因為呼叫了Wait(),Sleep()或Join()等方法處於封鎖狀態;
上面提到了Background狀態表示該執行緒在後臺執行,那麼後臺執行的執行緒有什麼特別的地方呢?其實後臺執行緒跟前臺執行緒只有一個區別,那就是後臺執行緒不妨礙程式的終止。一旦一個程式所有的前臺執行緒都終止後,CLR(通用語言執行環境)將通過呼叫任意一個存活中的後臺程式的Abort()方法來徹底終止程式。
執行緒的優先順序
當執行緒之間爭奪CPU時間時,CPU 是按照執行緒的優先順序給予服務的。在C#應用程式中,使用者可以設定5個不同的優先順序,由高到低分別是Highest,AboveNormal,Normal,BelowNormal,Lowest,在建立執行緒時如果不指定優先順序,那麼系統預設為ThreadPriority.Normal。
給一個執行緒指定優先順序,我們可以使用如下程式碼:
1 2 |
//設定優先順序為最低 myThread.Priority=ThreadPriority.Lowest; |
通過設定執行緒的優先順序,我們可以安排一些相對重要的執行緒優先執行,例如對使用者的響應等等。