在C#中啟用線程后,如果試圖使用Abort方法來終止線程,那么必定會拋出“正在終止線程”的異常,一開始我也想過如何來避免這種異常出現,花了不少氣力,但最后發現全是徒勞。
原因是一個正在運行的線程被終止在C#的機制中是屬於非正常結束,所以必定會爆出異常,所以我們也大可不必因為在代碼方面的“潔癖”非得找到一個方法來阻止這種異常出現。
也有人提出采用join()方法來阻止,但很多情況下這並不能完全滿足我們的要求,比如我們有一個后台的監聽線程,如果我們的確想終止它,如果我們采用了join方法,那么我們不想發生的情況就會出現,我們的界面會因為執行了join而卡死在那里,為什么呢?因為我們的監聽線程一般來說都是一個持續運行的線程,所以我們大可不必因為介意爆出異常而采用join的方法而導致程序假死。
我也在網上看見有人提出過,要終止線程最好是在執行線程的代碼中自然終止,這個說法本身沒有錯,但對於我上面說到的監聽線程,要自然結束是不可能辦到的。
從上面的分析我們可以看出,C#中的線程一旦開啟,那么只有等這個線程執行完,自然結束,自然被系統回收才不會爆出異常,任何一種外部的強制中斷都會被認為是異常的,任意一個線程在本質上都和我們的主線程(Main函數所在的線程)一樣,都必須按照順序執行完所有的語句方才結束當前線程,如果在所有的語句沒有執行完的時候就被終止了,這至少是與我們設計的理想狀態有差異的。
所以我覺得在遇到C#中的“正在終止線程”異常的時候,可以大膽的用try{}catch()來處理(丟棄異常信息或將異常友好化),而不是阻止這個異常的出現,阻止這個異常的出現明顯有兩個壞處:
第一、耗費的代價實在太高
第二、對於線程的干涉手段過於復雜,不便於維護線程
我的解決方法是:
按 “停止” 按鈕后,賦值某個變量為False,在線程執行的循環任務While、Foreach 里加上判斷語句 if (!tt) { continue; },效果為按下停止按鈕后,跳出循環。。等同於不執行任務了,其實線程還沒有關閉,只是在空閑中,可以新開一個線程在后台關閉線程1,然后再自動關閉自身。這樣也解決了t1.Join();卡死界面的問題。