.Net的公用語言運行時(Common Language Runtime,CLR)能區分兩種不同類型的線程:前台線程和后台線程。這兩者的區別就是:應用程序必須運行完所有的前台線程才可以退出;而對於后台線程,應用程序則可以不考慮其是否已經運行完畢而直接退出,所有的后台線程在應用程序退出時都會自動結束。
.Net環境使用Thread建立的線程默認情況下是前台線程,即線程屬性IsBackground= false,在進程中,只要有一個前台線程未退出, 進程就不會終止。主線程就是一個前台線程。
.Net環境使用Thread建立的線程默認情況下是前台線程,即線程屬性IsBackground= false,在進程中,只要有一個前台線程未退出, 進程就不會終止。主線程就是一個前台線程。
而后台線程不管線程是否結束,只要所有的前台線程都退出(包括正常退出和異常退出)后,進程就會自動終止。一般后台線程用於處理時間較短的任務,如在一個Web服務器中可以利用后台線程來處理客戶端發過來的請求信息。而前台線程一般用於處理需要長時間等待的任務,如在Web服務器中的監聽客戶端請求的程序,或是定時對某些系統資源進行掃描的程序。
需要明白的概念性問題:
線程是寄托在進程上的,進程都結束了,線程也就不復存在了!
只要有一個前台線程未退出,進程就不會終止!即說的就是程序不會關閉!(即在資源管理器中可以看到進程未結束。)
測試代碼:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } /// <summary> /// 彈出窗體Form2 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button1_Click(object sender, EventArgs e) { Form2 _frm2 = new Form2(); _frm2.Show(); } } public partial class Form2 : Form { public Form2() { InitializeComponent(); } Thread _Thread = null; private void Form2_Load(object sender, EventArgs e) { _Thread = new Thread(() => { while (true) { /*制造無限循環,等待用戶關閉線程*/ } }); _Thread.IsBackground = false;//false:設置為前台線程,系統默認為前台線程。 //_Thread.IsBackground = true;//true:后台線程 _Thread.Start(); } }
如設為前台線程,即IsBackground = False,關閉窗體2,在關閉窗體1,雖然窗體1關閉了,然而應用程序還是停留在資源管理器中。
如設為后台線程,即IsBackground = True, 關閉窗體1后,應用程序立刻從資源管理器中結束。
補充說明1:

private void Form2_Load(object sender, EventArgs e) { Thread _Thread = new Thread(() => { while (true) { /*制造無限循環,等待用戶關閉線程*/ this.BeginInvoke(new MethodInvoker(() => { this.Text = ""; })); Thread.Sleep(3000); } }); _Thread.IsBackground = true; _Thread.Start(); } //如果_Thread.IsBackground = true;為后台線程 //場景1:打開Form1窗口后,立刻點擊Button按鈕彈出Form2窗口,此時Form2窗口中的線程已經啟動了, //操作1:立刻關閉Form1窗口(主線程),此時不會出現任何的錯誤消息,同時資源管理器中ThreadDemo進程已經退出。 //操作2:此時關閉Form2窗口,大概等待3秒后,程序會出現崩潰的消息,其原因是因為Form2窗口中的線程有操作UI的代碼,而此時的Form2窗口已經關閉了(窗體對象已經釋放) }
補充說明2:

private void Form2_Load(object sender, EventArgs e) { Thread _Thread = new Thread(() => { while (true) { //if (this.IsHandleCreated) /*制造無限循環,模型耗時的任務*/ this.BeginInvoke(new MethodInvoker(() => { this.Text = ""; })); Thread.Sleep(3000); } }); _Thread.IsBackground = false; _Thread.Start(); } //如果_Thread.IsBackground = false;為前台線程 //場景1:打開Form1窗口后,立刻點擊Button按鈕彈出Form2窗口,此時Form2窗口中的線程已經啟動了, //操作(1):立刻關閉Form1窗口(主線程),大概等待3秒后,程序會出現崩潰的消息。 //操作(2):此時關閉Form2窗口,現象和上面一樣。 //,其原因是因為Form2窗口中的線程有操作UI的代碼而此時的Form2窗口已經關閉了(窗體對象已經釋放) //此處如果程序不崩潰的話(if (this.IsHandleCreated)加上這句的話),則上面的兩個操作可以在資源管理器中看到線程ThreadDemo一直存在進程中。 }
如果想讓上面的程序不崩潰可以使用:

if (this.IsHandleCreated) { /*制造無限循環,模型耗時的任務*/ this.BeginInvoke(new MethodInvoker(() => { this.Text = ""; })); }
if (!this.IsDisposed ) 也是可以的。判斷當前窗體是否已經釋放。(備注:釋放的窗體是不能操作界面UI元素的。)