引言:程序員
最近一段時間都在研究關於.Net線程的內容,以爲線程是每一個程序員都應該掌握的,因此寫下這個線程的系列但願能給你們學習過程當中一些幫助,同時也是本身對線程的鞏固,當中若是有什麼錯漏還請你們指出,這樣咱們能夠互相獲得進步。編程
目錄:多線程
1、線程的介紹異步
2、線程調度和優先級ide
3、前臺線程和後臺線程學習
4、簡單線程的使用spa
1、線程的介紹操作系統
在介紹線程以前, 頗有必要知道什麼是進程,以及與線程的關係。.net
進程(Process)是應用程序的實例要使用的資源的一個集合(從能夠簡化理解:進程就是一種資源,是應用程序所用的資源)。每一個應用程序都在各自的進程中運行來確保應用程序不受其餘應用程序的影響,若是一個應用程序失敗了, 只會影響本身的進程,其餘進程中的應用程序能夠繼續運行。進程是操做系統爲咱們提供的一種保護應用程序的一種機制。線程
線程是進程中基本執行單元, 一個進程中能夠包含多個線程,在進程入口執行的第一個線程是一個進程的主線程,在.Net應用程序中,都是以Main()方法做爲程序的入口的, 因此在程序運行過程當中調用這個方法時,系統就會自動建立一個主線程。(他們之間的關係簡單說:線程是進程的執行單元,進程是線程的一個容器了)。
2、線程調度和優先級
Windows之因此被稱爲搶佔式多線程操做系統,是由於線程能夠在任意時間被搶佔,並調度另外一個線程。每一個線程都分配了從0~31的一個優先級。系統首先把高優先級的線程分配給CPU執行。Windows 支持7個相對線程優先級:Idle,Lowest,Below Normal,Normal,Above Normal,Highest和Time-Critical,Normal是默認的線程優先級,然而在程序中能夠經過設置Thread的Priority屬性來改變線程的優先級,它的類型爲ThreadPriority枚舉類型,包含枚舉有:Lowest,BelowNormal,Normal,AboveNormal和Highest,CLR爲本身保留了 Idle和Time-Critical優先級。具體每一個枚舉值含義以下表:
成員名稱 | 說明 |
---|---|
Lowest | 能夠將 Thread何其餘優先級的線程以後。 |
BelowNormal | 能夠將 Thread Normal 優先級的線程以後,在具備 Lowest 優先級的線程以前。 |
Normal | 能夠將 Thread AboveNormal 優先級的線程以後,在具備 BelowNormal 優先級的線程以前。 默認狀況下,線程具備 Normal 優先級。 |
AboveNormal | 能夠將 Thread Highest 優先級的線程以後,在具備 Normal 優先級的線程以前。 |
Highest | 能夠將 Thread 其餘優先級的線程以前。 |
3、前臺線程和後臺線程
在.net中線程分爲前臺線程和後臺線程,在一個進程中,當全部前臺線程中止運行時,CLR會強制結束仍在運行的任何後臺線程,這些後臺線程直接被終止,不會拋出異常。
因此咱們應該在前臺線程中執行咱們確實要完成的事情,另外, 應該把非關鍵的任務使用後臺線程,咱們用Thread建立的是線程爲前臺線程。讓咱們經過下面的一段代碼來看看前臺線程和後臺線成的區別:
using System; using System.Threading; class Program { static void Main(string[] args) { // 建立一個新線程(默認爲前臺線程) Thread backthread = new Thread(Worker); // 使線程成爲一個後臺線程 backthread.IsBackground = true; // 經過Start方法啓動線程 backthread.Start(); // 若是backthread是前臺線程,則應用程序大約5秒後才終止 // 若是backthread是後臺線程,則應用程序當即終止 Console.WriteLine("Return from Main Thread"); } private static void Worker() { // 模擬作10秒 Thread.Sleep(5000); // 下面語句,只有由一個前臺線程執行時,纔會顯示出來 Console.WriteLine("Return from Worker Thread"); } }
運行上面代碼能夠發現:控制檯中顯示字符串: Return form Main Thread 後就退出了, 字符串 Return from Worker Thread字符串根本就沒有顯示,這是由於此時的backthread線程爲後臺線程,當主線程(執行Main方法的線程,主線程固然也是前臺線程了)結束運行後,CLR會強制終止後臺線程的運行,整個進程就被銷燬了,並不會等待後臺線程運行完後才銷燬。若是把 backthread.IsBackground = true; 註釋掉後, 就能夠看到控制檯過5秒後就輸出 Return from Worker Thread。再在Worker方法最後加一句 代碼:Console.Read(); 就能夠看到這樣的結果了:
注意:有些人可能會問我不想把 backthread.IsBackground = true;註釋掉, 又想把Worker()方法中的字符串輸出在控制檯上怎麼作呢? 實際上是有解決的辦法的, 咱們能夠調用thread.Join()方法來實現,Join()方法能保證主線程(前臺線程)在異步線程thread(後臺線程)運行結束後纔會運行。
實現代碼以下:
using System; using System.Threading; class Program { static void Main(string[] args) { // 建立一個新線程(默認爲前臺線程) Thread backthread = new Thread(Worker); // 使線程成爲一個後臺線程 backthread.IsBackground = true; // 經過Start方法啓動線程 backthread.Start(); backthread.Join(); // 模擬主線程的輸出 Thread.Sleep(2000); Console.WriteLine("Return from Main Thread"); Console.Read(); } private static void Worker() { // 模擬作3秒 Thread.Sleep(3000); // 下面語句,只有由一個前臺線程執行時,纔會顯示出來 Console.WriteLine("Return from Worker Thread"); } }
運行結果(調用Join方法後後臺線程會阻塞主線程因此主線程會後輸出):
4、簡單線程的使用
其實在上面介紹前臺線程和後臺線程的時候已經經過ThreadStart委託建立了一個線程了,此時已經實現了一個多線程的一個過程,爲此係列中將多線程也是作一個鋪墊吧。下面經過ParameterizedThreadStart委託的方式來實現多線程。
以ParameterizedThreadStart委託的方式來實現多線程:
using System; using System.Threading; class Program { static void Main(string[] args) { // 建立一個新線程(默認爲前臺線程) Thread backthread = new Thread(new ParameterizedThreadStart(Worker)); // 經過Start方法啓動線程 backthread.Start("123"); // 若是backthread是前臺線程,則應用程序大約5秒後才終止 // 若是backthread是後臺線程,則應用程序當即終止 Console.WriteLine("Return from Main Thread"); } private static void Worker(object data) { // 模擬作5秒 Thread.Sleep(5000); // 下面語句,只有由一個前臺線程執行時,纔會顯示出來 Console.WriteLine(data + " Return from Worker Thread"); Console.Read(); } }
注意:此時Worker方法傳入了一個參數,而且Start方法也傳遞了一個字符傳參數。 對比與以前建立Thread的不一樣,
運行結果爲:
寫到這裏, 本系列的第一篇差很少講完了,在後續的文章將會介紹Thread方法的使用以及經過一些例子來展現他們的不一樣之處(像Abort()方法Interrupt方法等)對於線程的一些高級使用(如線程池,並行編程和PLINQ、線程同步和計時器)都會在後續中講到。