C#.Net前台線程與后台線程的區別


.Net的公用語言運行時(Common Language Runtime,CLR)能區分兩種不同類型的線程:前台線程和后台線程。這兩者的區別就是:應用程序必須運行完所有的前台線程才可以退出;而對於后台線程,應用程序則可以不考慮其是否已經運行完畢而直接退出,所有的后台線程在應用程序退出時都會自動結束。

  .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();
        }
    }
測試結果:注意在Debug模式下,看看vs是否關閉!!! 或者通過Realse模式,觀看【資源管理器】中的應用程序線程是否關閉。

如設為前台線程,即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窗口已經關閉了(窗體對象已經釋放)

    }
View Code

補充說明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一直存在進程中。

    }
View Code

 

如果想讓上面的程序不崩潰可以使用:

  if (this.IsHandleCreated)
                    {
                        /*制造無限循環,模型耗時的任務*/
                        this.BeginInvoke(new MethodInvoker(() => { this.Text = ""; }));
                    }
View Code

 if (!this.IsDisposed ) 也是可以的。判斷當前窗體是否已經釋放。(備注:釋放的窗體是不能操作界面UI元素的。)


免責聲明!

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



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