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


      我們在C#夯實基礎之多線程一:初識多線程》一文中第二部分中指出,既然windows最終發展出了多線程模型,按理說,我們直接使用一個.NetFramework的線程類就可以直接擼代碼了,但在這之前,我們還需要認識一下線程的一些基本特性,它們的出現並不是多余的,而是為了解決一部分問題出現的,畢竟存在即合理,我們先說主線程、前台線程和后台線程:

一.主線程、前台線程與后台線程

   相信前幾年,大家都用過迅雷,用來下載文件是非常方便的,更重要的是速度快。那么,它的速度非常之快,全速下載的時候明顯地拉慢了整個系統的響應時間,說明他占用了大量的系統資源。那它為什么這么快?知乎上的yskin用戶解釋說一個下載任務進來,迅雷把文件平分成10份,然后開10個線程分別下載。這時主界面是一個單獨的線程,並不會因為下載文件而卡死。而且主線程可以控制下屬線程,比如某個線程下載緩慢甚至停止,主線程可以把它強行關掉並重啟另外一個線程。 這么多線程同時工作,正常情況下,下載速度會有質的提升。 

   那么,問題來了,當我暫停這個下載任務時,后面10個線程會關掉,但界面線程關閉掉這10個線程的時候,我們並沒有察覺,它們在后台悄默聲地就關掉了。這10個線程就是我們說的后台線程 

現在,我們把迅雷軟件退出了,那么所有的下載任務都關掉了,下載任務背后的線程自然也會關掉,這個迅雷軟件運行的線程就是我們說的主線程,它是一個前台線程 

但當我們再在網頁中重新找到可下載的內容時,迅雷的資源嗅探又可以檢測到這些內容,交提示我們是否要下載。它不隨着前面迅雷軟件的退出而退出。 

   如果你覺得這個例子不好理解,《C#高級編程》中也有一個,當你使用word來編輯文檔時,它會實時提供一些拼寫檢查,當你需要打印文檔時,可以選擇后台打印,在打印機打印文檔的同時,你可以繼續編輯當前文檔。同時word文檔關閉時,這個打印任務可繼續執行,直到打印出來,但拼寫檢查任務不會再執行。 

這就是主線程、前台線程與后台線程的一些類比。下面,我們來說結論。 

   當一個程序啟動時,就有一個進程被操作系統(OS)創建,與此同時一個線程也立刻運行,該線程通常叫做程序的主線程Main Thread),因為它是程序開始時就執行的,如果你需要再創建線程,那么創建的線程就是這個主線程的子線程,它是前台線程。 

   新建的子線程可以是前台線程或者后台線程,前台線程必須全部執行完,即使主線程關閉掉,這時進程仍然存活。后台線程在未執行完成時,如果前台線程關掉,則后台線程也會停掉,且不拋出異常。也就是說,前台線程與后台線程唯一的區別是后台線程不會阻止進程終止。可以在任何時候將前台線程修改為后台線程。

二.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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM