咱們在《C#夯實基礎之多線程一:初識多線程》一文中第二部分中指出,既然windows最終發展出了多線程模型,按理說,咱們直接使用一個.NetFramework的線程類就能夠直接擼代碼了,但在這以前,咱們還須要認識一下線程的一些基本特性,它們的出現並非多餘的,而是爲了解決一部分問題出現的,畢竟存在即合理,咱們先說主線程、前臺線程和後臺線程:html
一.主線程、前臺線程與後臺線程編程
相信前幾年,你們都用過迅雷,用來下載文件是很是方便的,更重要的是速度快。那麼,它的速度很是之快,全速下載的時候明顯地拉慢了整個系統的響應時間,說明他佔用了大量的系統資源。那它爲何這麼快?知乎上的yskin用戶解釋說『一個下載任務進來,迅雷把文件平分紅10份,而後開10個線程分別下載。這時主界面是一個單獨的線程,並不會由於下載文件而卡死。並且主線程能夠控制下屬線程,好比某個線程下載緩慢甚至中止,主線程能夠把它強行關掉並重啓另一個線程。 』這麼多線程同時工做,正常狀況下,下載速度會有質的提高。 windows
那麼,問題來了,當我暫停這個下載任務時,後面10個線程會關掉,但界面線程關閉掉這10個線程的時候,咱們並沒有察覺,它們在後臺悄默聲地就關掉了。這10個線程就是咱們說的後臺線程。 多線程
如今,咱們把迅雷軟件退出了,那麼全部的下載任務都關掉了,下載任務背後的線程天然也會關掉,這個迅雷軟件運行的線程就是咱們說的主線程,它是一個前臺線程。 spa
但當咱們再在網頁中從新找到可下載的內容時,迅雷的資源嗅探又能夠檢測到這些內容,交提示咱們是否要下載。它不隨着前面迅雷軟件的退出而退出。 操作系統
若是你以爲這個例子很差理解,《C#高級編程》中也有一個,當你使用word來編輯文檔時,它會實時提供一些拼寫檢查,當你須要打印文檔時,能夠選擇後臺打印,在打印機打印文檔的同時,你能夠繼續編輯當前文檔。同時word文檔關閉時,這個打印任務可繼續執行,直到打印出來,但拼寫檢查任務不會再執行。 線程
這就是主線程、前臺線程與後臺線程的一些類比。下面,咱們來講結論。 code
當一個程序啓動時,就有一個進程被操做系統(OS)建立,與此同時一個線程也馬上運行,該線程一般叫作程序的主線程(Main Thread),由於它是程序開始時就執行的,若是你須要再建立線程,那麼建立的線程就是這個主線程的子線程,它是前臺線程。 htm
新建的子線程能夠是前臺線程或者後臺線程,前臺線程必須所有執行完,即便主線程關閉掉,這時進程仍然存活。後臺線程在未執行完成時,若是前臺線程關掉,則後臺線程也會停掉,且不拋出異常。也就是說,前臺線程與後臺線程惟一的區別是後臺線程不會阻止進程終止。能夠在任什麼時候候將前臺線程修改成後臺線程。blog
二.C#中的前臺線程與後臺線程
在C#中,Thread類默認建立的是前臺線程,經過線程池(後面會講到)建立的線程都是後臺線程。
1.建立前臺線程和後臺線程
1 static void Main(string[] args) 2 { 3 //當前主線程是個前臺線程,且不能修改成後臺線程 4 Console.WriteLine(Thread.CurrentThread.IsBackground); 5 6 //Thread建立的線程是前臺線程 7 Thread th = new Thread(delegate() { Console.WriteLine("start a new thread"); }); 8 Console.WriteLine(th.IsBackground); 9 10 //Task使用程序池建立線程,默認爲後臺線程 11 Task task = new Task(() => Console.WriteLine("start a new task")); 12 13 Console.Read(); 14 }
輸出結果:
2.修改前臺線程爲後臺線程
1 static void Main(string[] args) 2 { 3 //修改前臺線程爲後臺線程 4 Thread th = new Thread(delegate() { Console.WriteLine("start a new thread"); }); 5 Console.WriteLine(th.IsBackground); 6 th.Start(); 7 th.IsBackground = true; 8 Console.WriteLine(th.IsBackground); 9 10 Console.Read(); 11 }
輸出結果
在C#中,前臺線程能夠修改成後臺線程,這是由HostProtectionAttribute屬性的SelfAffectingThreading字段決定的,若是能夠變成後臺線程,則值爲true.
3.前臺線程阻止進程的關閉
static void Main(string[] args) { //前臺線程阻止了主線程的關閉 Thread th = new Thread(delegate() { Thread.Sleep(6000); Console.WriteLine("start a new thread"); }); th.Start(); Console.WriteLine("main thread end"); }
輸出結果:這裏主線程立刻執行完成,並不立刻關閉,前臺線程等待6秒再執行輸出
4.後臺線程不阻止進程的關閉
1 static void Main(string[] args) 2 { 3 //後臺線程不阻止主線程的關閉 4 Thread th = new Thread(delegate() 5 { 6 Thread.Sleep(6000); 7 Console.WriteLine("start a new thread"); 8 9 }); 10 th.IsBackground = true; 11 th.Start(); 12 13 Console.WriteLine("main thread end"); 14 }
結果:不等線程執行完成,主線程執行完畢後自動退出。
三.參考文檔
http://technet.microsoft.com/zh-cn/library/system.threading.thread.isbackground