1. windows為什麼支援線程?
2. 線程開銷
3. 線程調度和線程優先順序
4. 前台線程和後台線程
5. 線程的Hello World程式
<1>. windows為什麼支援線程?
早期的windows系統是沒有”線程“概念的,整個系統只能運行著一個執行線程,這可能阻塞其他任務的執行,帶來極其差的使用者體驗,基於上述及其作業系統的健壯性,可靠性等,windows引入了“線程”的概念。 線程可以看作是對CPU的虛擬。ndows為什麼支援線程
<2>. 線程開銷
雖然多線程技術能夠在一定程度上增加使用者 互動體驗,但是作業系統建立線程並不是沒有代價的,具體來講:
2.1 windows核心需要建立“線程核心對象”,線程核心對象中包含作業系統需要掌握線程的基本資料
2.2 線程環境塊TEB,TEB中包含線程異常處理鏈首,執行緒區域儲存資料等資訊
2.3 使用者模式棧
2.4 核心模式棧,應用程式向作業系統的核心模式函數傳遞參數時,windows將使用者模式下的參數複製到核心棧中。
2.5 dll attach和dll detach通知,windows載入dll時,將會發出DLL_THREAD_ATTACH通知,dll卸載時發出DLL_THREAD_DETACH命令,如果一個 應用程式需要載入大量的dll的話,顯然對效能的影響是比較大的。
<3>. 線程調度和線程優先順序
在windows上執行的線程在執行了一定時間(一個時間片)後,windows將會進行“調度”,windows按照優先順序的高低選擇程式開始運行,也就是說如果存在一個優先順序是22的線程能夠執行,那麼windows將不會調用優先順序為21的線程。但是windows是一種“搶佔式”的作業系統(在windows上執行的線程能夠在任何時候被搶佔),如果一個具有較高優先順序的線程準備好運行,並且當前啟動並執行是較低優先順序的線程,windows將迫使較低優先順序線程停止運行,開始運行較高優先順序的線程。
由於windows上線程調用是(籠統的講)通過線程的優先順序來實現的,那麼如果我們想使我們的程式能夠被盡量多的調度,就需要設定線程的優先順序,windows的優先順序是使用數字表示的,在c#中將其抽象為ThreadPriority枚舉類型:
[Serializable] [ComVisible(true)] public enum ThreadPriority { Lowest = 0, BelowNormal = 1, Normal = 2, AboveNormal = 3, Highest = 4,
}
通常情況下,我們是不需要設定線程的優先順序,或者將其設定成Normal優先順序。
<4>. 前台線程和後台線程
CLR將線程分為“前台線程”和“後台線程”。如果一個進程的所有前台線程結束,那麼CLR將認為該進程已經結束,將自動結束該進程的後台線程,這些後台線程終止時,不產生異常。在c#中,使用Thread類的IsBackground方法來設定。
public bool IsBackground { get; set; }
通過線程池建立的線程預設是後台線程,通過 Thread t = new Thread(DoWork);形式建立的線程預設是前台線程,除非使用IsBackground設定成false。下面是一個測試代碼:
class Program { static void Main(string[] args) { Thread t = new Thread(DoWork); t.IsBackground = false; t.Start(); Console.WriteLine("Returning from Main"); } private static void DoWork() { Thread.Sleep(10000); // 下面的代碼只有在前台線程才能夠執行 Console.WriteLine("Returning from worker"); }
}
<5>. 線程的Hello World程式
c#中通過System.Threading.Thread建立一個線程是比較簡單的,Thread的常用建構函式:
public Thread(ParameterizedThreadStart start); // 建立線程,並向線程中傳遞參數
public Thread(ThreadStart start); // 建立線程,但是無法向啟動的線程中傳遞參數,主要是ThreadStart委託定義的原因
public delegate void ThreadStart();
建立了一個Thread對象之後,調用Start方法開始啟動線程。
public void Start();
完成代碼如下:
class Program { static void Main(string[] args) { Thread t = new Thread(DoWork); Console.WriteLine("Start the new thread..."); t.Start(); Console.WriteLine("Wait the thread to end ."); // 等待線程t結束 t.Join(); Console.WriteLine("Thread Ends"); Console.WriteLine("Press any key to continue"); Console.ReadKey(); } private static void DoWork() { Console.WriteLine("In DoWork thread"); // 當前線程休眠一段時間,用來類比工作了一段時間 Thread.Sleep(1000); }
}