Thread類
Thread類相對於線程池中的線程,使用者有更多的控制權。該類允許創建前臺線程,設置線程優先級等。Thread類的構造函數重載為接受ThreadStart和ParameterizedThreadStart類型的委托參數。
1、給線程傳遞數據
給線程傳遞數據的兩種方式:
1.使用帶ParameterizedThreadStart委托參數的Thread構造函數:
//定義一個數據類型,傳遞給線程 public struct Data { public string Message; } //創建一個方法,將方法給線程的ParameterizedThreadStart委托 staticvoid ThreadMainWithParameters(object obj) { Data d = (Data)obj; Console.WriteLine("Running in a thread, received {0}", d.Message); } static void Main() { Data d = new Data { Message = "Info" };//創建一個數據實例 Thread t2 = new Thread(ThreadMainWithParameters);//創建線程 t2.Start(d);//啟動線程,並傳遞參數 }
2.自定義一個類,把線程的方法定義為實例方法,然後初始化實例的數據後啟動線程。
//定義一個類,用於存放線程需要的數據和線程啟動的方法 public class MyThread { private string data;//線程數據 public MyThread(string data) { this.data = data; } //線程啟動方法 public void ThreadMain() { Console.WriteLine("Running in a thread, data: {0}", data); } }static void Main() { MyThread obj = new MyThread("info");//創建實例信息 Thread t3 = new Thread(obj.ThreadMain);//啟動實例方法 t3.Start(); }
2、後臺線程
如果應用程序內有任何一個前臺線程在運行,那麽應用程序就在運行。Thread類創建的線程默認時前臺線程,線程池中創建的線程是後臺線程。在使用Thread類創建線程時,可以設置IsBackground屬性,以設置創建的Thread線程時後臺線程還是前臺線程。例如:
//創建線程方法,以在主線程中調用 static void ThreadMain() { Console.WriteLine("Thread {0} started", Thread.CurrentThread.Name); Thread.Sleep(3000); Console.WriteLine("Thread {0} completed", Thread.CurrentThread.Name); } static void Main() { Thread t1 = new Thread(ThreadMain);
t1.Name = "MyNewThread"; t1.Start();
Thread.Sleep(100); Console.WriteLine("Main thread ending now..."); /*******************輸出********************
* Thread MyNewThread started * Main thread ending now... * Thread MyNewThread completed * *****************************************/ }
可以看到,主線程先完成任務。但是主線程內啟動的新線程是前臺線程(默認),導致主線程結束任務後,新線程仍在寫入控制臺輸出。如果在線程啟動前,將線程的IsBackground屬性設置為true,主線程結束時,會終止新線程的執行(不論是否完成任務)。
static void Main() { Thread t1 = new Thread(ThreadMain); t1.Name = "MyNewThread"; t1.IsBackground = true; t1.Start(); Thread.Sleep(100); Console.WriteLine("Main thread ending now..."); /*******************輸出******************** * Thread MyNewThread started * Main thread ending now... * *****************************************/ }
後臺線程適合用於完成後臺任務。
3、線程的優先級
線程由操作系統調度。給線程指定優先級,將影響線程調度順序。優先級越高的線程,將會得到系統優先調度在CPU上運行。如果線程在等待資源,它就會停止運行,並釋放CPU。
線程必須等待的可能原因:響應睡眠指令、等待磁盤I/O完成、等待網絡包到達等。如果線程不主動釋放CPU,線程調度器就會搶占該線程。線程由一個時間量,它可以持續使用CPU,直到時間到達(如果沒有更高優先級的線程時)。如果優先級相同的多個線程等待CPU,線程調度器會使用一個循環調度原則,將CPU逐一交個線程使用。如果線程被其他線程搶占,那麽它會排隊到最後去。
只有優先級相同的多個線程同時在運行時,才能用上時間量和循環規則。優先級是動態的:如果線程是CPU密集型,一直需要CPU,而且不等待資源,其優先級就降低為用該線程定義的基本優先級;如果線程在等待資源,它的優先級會提高。由於優先級的提高,所以線程可能在下一等待結束時獲得CPU。
線程的Priority屬性,可以設置線程的優先級。線程指定優先級時,可能降低其他線程的運行概率。所以,可以根據需要短暫改變優先級。
4、控制線程
調用Thread對象的Start()方法可以創建線程。但是,新線程並不是出於Running狀態,而是Unstarted狀態。當線程調度器調用線程時,線程則會改為Running狀態。其ThreadState屬性可以獲得線程的狀態。
線程類的靜態方法Sleep(),會使線程處於WaitSleepJoin狀態,在等待一段時間後,線程將再次被喚醒。
如果要停止一個線程,可以調用方法Abort()。調用該方法,會在接到終止命令的線程中拋出ThreadAbortException類型異常。捕獲該異常,可以在線程結束前做一些清理工作。如果再調用方法ResetAbort(),可能有機會再收到異常後繼續運行。如果線程沒有重置,接收到終止請求的線程的狀態就從AbortRequested改為Aborted。
調用Join()方法可以等待線程的結束。該方法會停止當前線程,並把它設置為WaitSleepJoin狀態,直到加入的線程完成。
Thread類