以ThreadStart方式實現多線程多線程
3.1 使用ThreadStart委託異步
這 裏先以一個例子體現一下多線程帶來的好處,首先在Message類中創建一個方法ShowMessage(),裏面顯示了當前運行線程的Id,並使用 Thread.Sleep(int ) 方法模擬部分工做。在main()中經過ThreadStart委託綁定Message對象的ShowMessage()方法,而後經過 Thread.Start()執行異步方法。線程
1 public class Message 2 { 3 public void ShowMessage() 4 { 5 string message = string.Format("Async threadId is :{0}", 6 Thread.CurrentThread.ManagedThreadId); 7 Console.WriteLine(message); 8 9 for (int n = 0; n < 10; n++) 10 { 11 Thread.Sleep(300); 12 Console.WriteLine("The number is:" + n.ToString()); 13 } 14 } 15 } 16 17 class Program 18 { 19 static void Main(string[] args) 20 { 21 Console.WriteLine("Main threadId is:"+ 22 Thread.CurrentThread.ManagedThreadId); 23 Message message=new Message(); 24 Thread thread = new Thread(new ThreadStart(message.ShowMessage)); 25 thread.Start(); 26 Console.WriteLine("Do something ..........!"); 27 Console.WriteLine("Main thread working is complete!"); 28 29 } 30 }請注意運行結果,在調用Thread.Start()方法後,系統以異步方式運行Message.ShowMessage(),而主線程的操做是繼續執行的,在Message.ShowMessage()完成前,主線程已完成全部的操做。
3.2 使用ParameterizedThreadStart委託code
ParameterizedThreadStart 委託與ThreadStart委託很是類似,但ParameterizedThreadStart委託是面向帶參數方法的。注意 ParameterizedThreadStart 對應方法的參數爲object,此參數能夠爲一個值對象,也能夠爲一個自定義對象。orm
1 public class Person 2 { 3 public string Name 4 { 5 get; 6 set; 7 } 8 public int Age 9 { 10 get; 11 set; 12 } 13 } 14 15 public class Message 16 { 17 public void ShowMessage(object person) 18 { 19 if (person != null) 20 { 21 Person _person = (Person)person; 22 string message = string.Format("\n{0}'s age is {1}!\nAsync threadId is:{2}", 23 _person.Name,_person.Age,Thread.CurrentThread.ManagedThreadId); 24 Console.WriteLine(message); 25 } 26 for (int n = 0; n < 10; n++) 27 { 28 Thread.Sleep(300); 29 Console.WriteLine("The number is:" + n.ToString()); 30 } 31 } 32 } 33 34 class Program 35 { 36 static void Main(string[] args) 37 { 38 Console.WriteLine("Main threadId is:"+Thread.CurrentThread.ManagedThreadId); 39 40 Message message=new Message(); 41 //綁定帶參數的異步方法運行結果:
42 Thread thread = new Thread(new ParameterizedThreadStart(message.ShowMessage)); 43 Person person = new Person(); 44 person.Name = "Jack"; 45 person.Age = 21; 46 thread.Start(person); //啓動異步線程
47 48 Console.WriteLine("Do something ..........!"); 49 Console.WriteLine("Main thread working is complete!"); 50 51 } 52 }
3.3 前臺線程與後臺線程對象
注意以上兩個例子都沒有使用Console.ReadKey(),但系統依然會等待異步線程完成後纔會結束。這是由於使用Thread.Start()啓動的線程默認爲前臺線程,而系統必須等待全部前臺線程運行結束後,應用程序域纔會自動卸載。blog
在第二節曾經介紹過線程Thread有一個屬性IsBackground,經過把此屬性設置爲true,就能夠把線程設置爲後臺線程!這時應用程序域將在主線程完成時就被卸載,而不會等待異步線程的運行。資源
3.4 掛起線程開發
爲了等待其餘後臺線程完成後再結束主線程,就可使用Thread.Sleep()方法。get
1 public class Message 2 { 3 public void ShowMessage() 4 { 5 string message = string.Format("\nAsync threadId is:{0}", 6 Thread.CurrentThread.ManagedThreadId); 7 Console.WriteLine(message); 8 for (int n = 0; n < 10; n++) 9 { 10 Thread.Sleep(300); 11 Console.WriteLine("The number is:" + n.ToString()); 12 } 13 } 14 } 15 16 class Program 17 { 18 static void Main(string[] args) 19 { 20 Console.WriteLine("Main threadId is:"+ 21 Thread.CurrentThread.ManagedThreadId); 22 23 Message message=new Message(); 24 Thread thread = new Thread(new ThreadStart(message.ShowMessage)); 25 thread.IsBackground = true; 26 thread.Start(); 27 28 Console.WriteLine("Do something ..........!"); 29 Console.WriteLine("Main thread working is complete!"); 30 Console.WriteLine("Main thread sleep!"); 31 Thread.Sleep(5000); 32 } 33 }
運行結果以下,此時應用程序域將在主線程運行5秒後自動結束
但 系統沒法預知異步線程須要運行的時間,因此用經過Thread.Sleep(int)阻塞主線程並非一個好的解決方法。有見及此,.NET專門爲等待異 步線程完成開發了另外一個方法thread.Join()。把上面例子中的最後一行Thread.Sleep(5000)修改成 thread.Join() 就能保證主線程在異步線程thread運行結束後纔會終止。
3.5 Suspend 與 Resume (慎用)
Thread.Suspend() 與 Thread.Resume()是在Framework1.0 就已經存在的老方法了,它們分別能夠掛起、恢復線程。但在Framework2.0中就已經明確排斥這兩個方法。這是由於一旦某個線程佔用了已有的資源, 再使用Suspend()使線程長期處於掛起狀態,當在其餘線程調用這些資源的時候就會引發死鎖!因此在沒有必要的狀況下應該避免使用這兩個方法。
3.6 終止線程
若想終止正在運行的線程,可使用Abort()方法。在使用Abort()的時候,將引起一個特殊異常 ThreadAbortException 。
若想在線程終止前恢復線程的執行,能夠在捕獲異常後 ,在catch(ThreadAbortException ex){...} 中調用Thread.ResetAbort()取消終止。
而使用Thread.Join()能夠保證應用程序域等待異步線程結束後才終止運行。
1 static void Main(string[] args) 2 { 3 Console.WriteLine("Main threadId is:" + 4 Thread.CurrentThread.ManagedThreadId); 5 6 Thread thread = new Thread(new ThreadStart(AsyncThread)); 7 thread.IsBackground = true; 8 thread.Start(); 9 thread.Join(); 10 11 } 12 13 //以異步方式調用
14 static void AsyncThread() 15 { 16 try 17 { 18 string message = string.Format("\nAsync threadId is:{0}", 19 Thread.CurrentThread.ManagedThreadId); 20 Console.WriteLine(message); 21 22 for (int n = 0; n < 10; n++) 23 { 24 //當n等於4時,終止線程
25 if (n >= 4) 26 { 27 Thread.CurrentThread.Abort(n); 28 } 29 Thread.Sleep(300); 30 Console.WriteLine("The number is:" + n.ToString()); 31 } 32 } 33 catch (ThreadAbortException ex) 34 { 35 //輸出終止線程時n的值
36 if (ex.ExceptionState != null) 37 Console.WriteLine(string.Format("Thread abort when the number is: {0}!", 38 ex.ExceptionState.ToString())); 39 40 //取消終止,繼續執行線程
41 Thread.ResetAbort(); 42 Console.WriteLine("Thread ResetAbort!"); 43 } 44 45 //線程結束
46 Console.WriteLine("Thread Close!"); 47 }
運行結果以下