1. 程式人生 > >多執行緒開發(1):主執行緒,前臺執行緒,後臺執行緒,守護執行緒,子執行緒,託管執行緒的關係

多執行緒開發(1):主執行緒,前臺執行緒,後臺執行緒,守護執行緒,子執行緒,託管執行緒的關係

1.主執行緒
當一個程式啟動時,就有一個程序被作業系統(OS)建立,與此同時一個執行緒也立刻執行,該執行緒通常叫做程式的主執行緒(Main Thread),因為它是程式開始時就執行的,如果你需要再建立執行緒,那麼建立的執行緒就是這個主執行緒的子執行緒。每個程序至少都有一個主執行緒,在Winform中,應該就是建立GUI的執行緒。主執行緒的重要性體現在兩方面:1.是產生其他子執行緒的執行緒;2.通常它必須最後完成執行比如執行各種關閉動作。

2.前臺執行緒,後臺執行緒,託管執行緒,守護執行緒

CLR能區分兩種不同型別的執行緒:前臺執行緒和後臺執行緒。這兩者的區別就是:應用程式必須執行完所有的前臺執行緒才可以退出;而對於後臺執行緒,應用程式則可以不考慮其是否已經執行完畢而直接退出,所有的後臺執行緒在應用程式退出時都會自動結束。 一個執行緒是前臺執行緒還是後臺執行緒可由它的IsBackground屬性來決定。這個屬性是可讀又可寫的。它的預設值為false,即意味著一個執行緒預設為前臺執行緒。我們可以將它的IsBackground屬性設定為true,從而使之成為一個後臺執行緒。
後臺執行緒又叫守護執行緒

,它被CLR認為是程式執行中可做出犧牲的途徑,即在任何時候都可能被忽略,因此,如果所有的前臺執行緒終止,當應用程式域解除安裝時,所有的後臺執行緒也會被自動終止。值得注意的是:前臺執行緒和後臺執行緒並不等同於主執行緒和工作執行緒,預設情況下,通過Thread.Start()方法建立的執行緒都自動成為前臺執行緒。把執行緒的IsBackground屬性設為 true就可以將執行緒配置為後臺執行緒。

託管執行緒或者是後臺執行緒,或者是前臺執行緒。 後臺執行緒不會使託管執行環境處於執行狀態,除此之外,後臺執行緒與前臺執行緒是一樣的。 一旦所有前臺執行緒在託管程序(其中 .exe 檔案是託管程式集)中被停止,系統將停止所有後臺執行緒並關閉。

3.子執行緒

預設情況,在新開啟一個子執行緒的時候,他是前臺執行緒,只有,將執行緒的IsBackground屬性設為true;他才是後臺執行緒 
當子執行緒是前臺執行緒,則主執行緒結束並不影響其他執行緒的執行,只有所有前臺執行緒都結束,程式結束 
當子執行緒是後臺執行緒,則主執行緒的結束,會導致子執行緒的強迫結束 
(個人理解,這樣設計的原因:因為後臺執行緒一般做的都是需要花費大量時間的工作,如果不這樣設計,主執行緒已經結束,而後臺工作執行緒還在繼續,第一有可能使程式陷入死迴圈,第二主執行緒已經結束,後臺執行緒即時執行完成也已經沒有什麼實際的意義)

4.名詞之間的關係總結

  託管執行緒包括前臺執行緒和後臺執行緒

  守護執行緒是後臺執行緒

  主執行緒是一個前臺執行緒,前臺執行緒可以是多個的

  子執行緒是從屬與主執行緒的,子執行緒可以是多個

5.DEMO:

    public partial class Form1 : Form
    {       
        public Form1()
        {
            j=1;
            InitializeComponent();
        }
        static int j;

        private void btnMultiThread_Click(object sender, EventArgs e)
        {
            Thread th = new Thread(new ThreadStart(MultiMethod));//子執行緒預設是前臺執行緒
            th.IsBackground = true;//將一個執行緒設定為後臺執行緒,就可以保證前臺執行緒關閉後,後臺執行緒也會停止執行。
            th.Start();          
            //this.lbCounter.Text = j.ToString();
        }

        private void MultiMethod()
        {
            for (int i = 0; i < 99999999; i++)
            {
                
            }
            j=10000;//j是上下文中的變數,屬於程序(static),所以是可以訪問的。
            //this.lbCounter.Text =j.ToString();//控制元件是屬於UI執行緒(主執行緒,前臺執行緒),直接跨執行緒是訪問不了的。
            MessageBox.Show("迴圈9999999次結束!");//MessageBox類是程序上下文環境中的資源,不屬於Form1主執行緒(前臺執行緒,UI執行緒)
            this.Invoke(new Action(() => { lbCounter.Text = j.ToString(); }));//跨執行緒需要使用主執行緒的Invoke方法
        }

        private void btnSingle_Click(object sender, EventArgs e)
        {
            MultiMethod();//UI執行緒是同步,會等待不少時間。
        }

        private void btnCloseUI_Click(object sender, EventArgs e)
        {
            this.Close();//前臺執行緒(UI執行緒,主執行緒)關閉,後臺執行緒會停止執行
        }
    }

6.參考資料