C#線程的生命週期分爲幾個階段:
一、未啓動狀態:當線程實例被建立但 Start 方法未被調用時的情況;
二、就緒狀態:當線程準備好運行並等待 CPU 週期時的情況;
三、不可運行狀態:下面的幾種狀況下線程是不可運行的:
1). 已經調用 Sleep 方法;
2). 已經調用 Wait 方法;
3). 經過 I/O 操做阻塞。
四、死亡狀態:當線程已完成執行或已停止時的情況。異步
一個簡單的不帶參數的線程:函數
//線程函數 public static void Task() { for (int i = 0; i < 10; i++) { Console.WriteLine("Task Print {0}", i); Thread.Sleep(1000); } } //建立簡單的線程,不帶任何參數 Thread th = new Thread(Task); th.Name = "PrintThread"; //啓動執行線程 th.Start(); //等待線程執行完畢 th.Join(); Console.WriteLine("Thread [{0}] Finished !", th.Name);
對於帶參數的線程方法,一般須要自定義一個線程參數類,示例:線程
//自定義的線程參數類 class ThreadParameter { private int size; public ThreadParameter(int s) { size = s; } //線程方法 public void ThreadMethod() { for (int i = 0; i < size; i++) { Console.WriteLine("Task1 Print {0}", i); Thread.Sleep(1000); } } } //實例化線程參數類 ThreadParameter tp = new ThreadParameter(10); //實例化線程對象 Thread th = new Thread(tp.ThreadMethod); th.Name = "PrintThread"; //啓動線程 th.Start(); //等待線程結束 th.Join(); Console.WriteLine("Thread [{0}] Finished !", th.Name);
Abort() 方法用於銷燬線程。經過拋出 threadabortexception 在運行時停止線程。這個異常不能被捕獲,若是有 finally 塊,控制會被送至 finally 塊。code
public static void ThreadProc() { try { for (int i = 0; i < 10; i++) { Console.WriteLine("Task1 Print {0}", i); Thread.Sleep(1000); } } //捕獲線程異常退出 catch (ThreadAbortException e) { Console.WriteLine(e); } finally { Console.WriteLine("Thread Finished !"); } } //實例化線程對象 Thread th = new Thread(ThreadProc); //啓動線程 th.Start(); //等待5秒後結束線程 Thread.Sleep(5000); th.Abort(); Console.WriteLine("Thread [{0}] Finished !", th.Name);
有時候一個函數的執行很長,不能一直等待函數執行完畢,但願在函數執行的時候主線程能夠完成些其餘的事情,而後再等待線程執行完畢。下面的代碼同步執行時會依次打印1~5數字,而異步執行的時候則是亂序的:orm
static void Test(string name) { Console.WriteLine("TestMethod: {0:yyyy-MM-dd HH:mm:ss.fff} {1}", DateTime.Now, name); } static void Main() { TestDelegate d = Test; Console.WriteLine("Beginning : {0:yyyy-MM-dd HH:mm:ss.fff}", DateTime.Now); //同步執行,依次打印 d("111"); d("222"); d("333"); d("444"); d("555"); //異步執行,會放入線程池中,打印亂序 var r1 = d.BeginInvoke("小明1", null, null); var r2 = d.BeginInvoke("小明2", null, null); var r3 = d.BeginInvoke("小明3", null, null); var r4 = d.BeginInvoke("小明4", null, null); var r5 = d.BeginInvoke("小明5", null, null); //此時異步執行尚未完成 Console.WriteLine("End : {0:yyyy-MM-dd HH:mm:ss.fff}", DateTime.Now); //等待異步執行完成 d.EndInvoke(r1); d.EndInvoke(r2); d.EndInvoke(r3); d.EndInvoke(r4); d.EndInvoke(r5); Console.WriteLine("線程所有執行完成"); Console.Read(); }
另一個定時器定時打印的例子:對象
//打印當前日期和時間 static void PrintPoint(object sender, ElapsedEventArgs e) { DateTime dtCurr = DateTime.Now; Console.WriteLine("{0:yyyy-MM-dd HH:mm:ss.fff}", dtCurr); Thread.Sleep(1000); } static void Main() { //構建定時器, System.Timers.Timer timer = new System.Timers.Timer(); timer.Interval = 1000; timer.Start(); //鏈接打印方式到定時器超時事件 timer.Elapsed += new ElapsedEventHandler(PrintPoint); Console.WriteLine("End"); Console.Read(); }
在主線程中使用EndInvoke仍是很麻煩,始終要阻塞等待。使用異步回調就能夠解決這個問題,當異步返回時自動調用回調函數:生命週期
//異步結束時的回調 public static void BackCall(IAsyncResult parameter) { //parameter.IsCompleted用於判斷異步方法是否已調用完成; if (parameter.IsCompleted) { //經過EndInvoke方法獲取異步方法的返回結果(類型與異步方法的結果一致) Console.Write(string.Format("回調完成,返回值")); } else { Console.Write("調用未完成"); } } TestDelegate td = PrintPoint; td.BeginInvoke(BackCall, null); Console.WriteLine("End"); Console.Read();