C#夯實基礎之多線程二:主線程、前臺線程與後臺線程

      咱們在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

相關文章
相關標籤/搜索