我們都知道,在這個行業,追求的就是用最少的時間學最多的知識,這是我寫這個系列最想達到的目標,在最快的時間內,幫助更多的人學習更多的線程知識。
前一篇,講述了線程基礎,給大家鋪墊了一個基礎,這一篇着重介紹線程的作用及其工作方式,順便小試牛刀一把。
現在我想提出,最直接的問題是:
為什么要使用線程?
為什么要使用線程?答案只有三點(歡迎補充^_^):
- 使用線程可以將代碼同其他代碼隔離。這將提高應用程序的可靠性,這不僅僅是應用程序所需要的,更是Windows引入線程的真正原因。
- 使用線程可以簡化編程。這個答案有利有弊,需要從兩方面考慮:第一點:使用線程的同時也就意味着會付出一些資源作為代價,對於現在的計算機,付出資源是值得的,因為它的資源根本沒有發掘出來。第二點:引用線程的時候是在需要相互協作的代碼時,不能隨便的引用線程,盲目的使用線程,只會增加代碼復雜度。
- 可以用線程來程序的實現並發執行,雙管齊下,效率,你懂的(∩_∩)。
說了這么些,總得試試手啊,使用線程?so easy:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Console.WriteLine("主線程:啟動專用線程..."); 6 Thread dedicatedThread = new Thread(StartCode); 7 8 dedicatedThread.Start(5); 9 10 11 Console.WriteLine("主線程:運行到此"); 12 Thread.Sleep(10000);//模擬主線程操作 13 dedicatedThread.Join(); 14 Console.WriteLine("主線程:運行完畢"); 15 } 16 17 private static void StartCode(Object obj) 18 { 19 Console.WriteLine("子線程:啟動代碼!{0}",obj); 20 Thread.Sleep(1000);//模擬代碼操作 21 22 } 23 }
下面是我兩次運行的結果:
這是最基本的線程運用,好像不難哦?但是不提倡這么用。
中間有個Join方法,Join的作用是:造成調用線程阻塞當前執行的任何代碼,直到dedicatedThread所代表的線程終止或銷毀。
同一個程序出現兩種輸出結果,這是為什么?程序的每次輸出不該是一樣的嗎?
兩種輸出的不一樣是因為Windows對兩個線程進行調度的方式不同,這無法控制。Windows搶占式多線程這一概念覺得了這因素。
這個知識點大家有必要了解,這個例子是個專用線程你可以這么用,但是建議應避免這么做,CLR的線程池可以更安全的完成這些事,如果你一定要創
建自己的線程,開始執行專用線程時,需考慮以下四點內容:
- 線程需要以非普通線程優先運行。線程池線程都是普通優先級運行,可以更改這個優先級,但不建議這么做。在不同的線程池操縱之間,優先級的更改是無法延續的(線程池這個概念下篇解析)。
- 需要線程表現為一個前台進程,防止應用程序在線程結束它的任務之前終止。(線程池的線程始終是后台線程,如果CLR要終止進程,它們就可能無法被迫完成任務)
- 一個計算限制的任務需要長時間的運行,就像例子中StartCode(),它執行的就是計算限制的任務。為長時間運行的任務創建一個專業線程,用於避免這個問題。
- 任務線程可能調用Abort()(屬於Thread)來提前終止它。
線程可以分為前台線程和后台線程
CLR將每個線程要么視為前台,要么視為后台線程。當一個進程中的所有前台線程停止運行時(也就是我們按右上角的X,關閉程序),CLR將強制終止仍在運行的后台線程直接終止,不會異常。
基於這個原因,前台線程的使用應該用於執行確實想完成的任務,就用個我們正在用瀏覽器(下面稱前台線程)做例子:
你正在瀏覽本篇內容,就意味着這個前台線程,正要完成你所需求的任務指令,解析HTML代碼,便於你的閱讀,這是首要任務。而加載書簽,讀取收藏網址的信息等,關鍵的后台功能,能在應用程序重啟的時候繼續執行,如果關閉前台線程,它們沒必要保持活動的狀態。
下面來看個前台線程和后台線程的程序實現:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Thread t = new Thread(StartCode); 6 // t.IsBackground = true; 7 t.Start(); 8 9 Console.WriteLine("主線程運行完畢!"); 10 } 11 12 private static void StartCode() 13 { 14 Console.WriteLine("開始執行子線程..."); 15 Thread.Sleep(10000);//模擬代碼操作 16 Console.WriteLine("子線程執行完畢!"); 17 18 } 19 }
這段可運行代碼就是默認模式,執行的前台代碼。它的輸出也是你能預測的:
在“開始執行子線程...”的時候,需要等待10秒。
去掉第6行的注釋,再看看運行結果:
它不會等待,並看不到“子線程執行完畢”這句話。
前台的好處是,你可以保證你的后台線程能執行完畢,后台線程的好處是,你不用管它的執行。
在一個線程的生存期中,任何時候都可以進行前后台互換。
CLR要提供前台線程和后台線程的概念來更好的支持應用程序域(俗稱AppDoMain),每個AppDoMain都可以運行一個單獨的應用程序,每個應用程序都有它的前台線程,一個應用程序退出,前台線程終止,對應的后台線程也要終止,但CLR線程仍然需要運行,使其他應用程序繼續運行,所有應用程序退出后,整個進程就可以銷毀了。CLR算是線程運行的一個空間。
最后,說個大家十分熟悉的功能,用過Visual Studio 的開發人員,我保證你們都體驗過這個功能。
智能提示都知道,這個是典型的線程運用,很快捷很舒心是不是?
當你寫代碼寫到興頭時,發現編譯器畫出紅線提示你,某處代碼出錯了。有沒有發現這個?怎么實現的?
在你停止輸入的時候,編譯器就會開始編譯代碼,檢測代碼中的出錯部分,很人性化,這大大提高了C#開發人員的工作效率,而在這,線程功不可沒,線程的力量可見一斑。
線程基礎還有一節重要的。下回講~~~更新有點慢,是為了寫出更好的博客。(^。^)y-~~