.Net中後臺線程和前臺線程的區別

.Net中的線程,可以分爲後臺線程和前臺線程。後臺線程與前臺線程並沒有本質的區別,它們之間唯一的區別就是:應用程序必須運行完所有的前臺線程纔可以退出;而對於後臺線程,應用程序則可以不考慮其是否已經運行完畢而直接退出,所有的後臺線程在應用程序退出時都會自動結束。其實,說白了就是當前臺線程都結束了的時候,整個程序也就結束了,即使還有後臺線程正在運行,此時,所有剩餘的後臺線程都會被停止且不會完成.但是,只要還有一個前臺線程沒有結束,那麼它將阻止程序結束.這就是爲什麼有些設計不夠完美的WinForm程序,在某種特定的情況下,即使所有的窗口都關閉了,但是在任務管理器的管理列表裏仍然可以找到該程序的進程,仍然在消耗着CPU和內存資源.因此,在WinForm程序中,關閉所有窗口前,應該停止所有前臺線程,千萬不要遺忘了某個前臺線程.應用程序進程的存亡由前臺線程決定而於後臺線程無關.這就是它們的區別.線程默認爲前臺線程。
此外,改變線程從前臺到後臺不會以任何方式改變它在CPU協調程序中的優先級和狀態。因爲前臺後線程與程序進程的優先級無關.
下面的代碼示例對比了前臺線程與後臺線程的行爲。創建一個前臺線程和一個後臺線程。前臺線程使進程保持運行,直到它完成它的 while 循環。前臺線程完成後,進程在後臺線程完成它的 while 循環之前終止。
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace TestBackgroundThread
{
    class Program
    {
        static void Main()
        {
            BackgroundTest shortTest = new BackgroundTest(10);
            Thread foregroundThread =
                new Thread(new ThreadStart(shortTest.RunLoop));
            foregroundThread.Name = "前臺線程";

            BackgroundTest longTest = new BackgroundTest(50);
            Thread backgroundThread =
                new Thread(new ThreadStart(longTest.RunLoop));
            backgroundThread.Name = "後臺線程";
            backgroundThread.IsBackground = true;

            foregroundThread.Start();
            backgroundThread.Start();

            //Console.ReadLine();   //不需要此行
        }
    }

    class BackgroundTest
    {
        int maxIterations;

        public BackgroundTest(int maxIterations)
        {
            this.maxIterations = maxIterations;
        }

        public void RunLoop()
        {
            String threadName = Thread.CurrentThread.Name;

            for (int i = 0; i < maxIterations; i++)
            {
                Console.WriteLine("{0} count: {1}",
                    threadName, i.ToString());
                Thread.Sleep(500);
            }
            Console.WriteLine("{0} finished counting.", threadName);
        }
    }
}

 

 

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


一個線程是前臺線程還是後臺線程可由它的IsBackground屬性來決定。這個屬性是可讀又可寫的。它的默認值爲false,即意味着一個線程默認爲前臺線程。我們可以將它的IsBackground屬性設置爲true,從而使之成爲一個後臺線程。


下面的例子是一個控制檯程序,程序一開始便啓動了10個線程,每個線程運行5秒鐘時間。由於線程的IsBackground屬性默認爲false,即它們都是前臺線程,所以儘管程序的主線程很快就運行結束了,但程序要到所有已啓動的線程都運行完畢纔會結束。示例代碼如下:

using System;
using System.Threading;

class MyApp
{
    public static void Main()
    {
        for (int i = 0; i < 10; i++)
        {
            Thread thread = new Thread(new ThreadStart(ThreadFunc));
            thread.Start();
        }
    }
 
    private static void ThreadFunc()
    {
        DateTime start = DateTime.Now;
        while ((DateTime.Now - start).Seconds < 5)
            ;
    }
}


接下來我們對上面的代碼進行略微修改,將每個線程的IsBackground屬性都設置爲true,則每個線程都是後臺線程了。那麼只要程序的主線程結束了,整個程序也就結束了。示例代碼如下:



using System;
using System.Threading; 

class MyApp
{
    public static void Main()
    {
        for (int i = 0; i < 10; i++)
        {
            Thread thread = new Thread(new ThreadStart(ThreadFunc));
            thread.IsBackground = true;
            thread.Start();
        }
    }

 
    private static void ThreadFunc()
    {
        DateTime start = DateTime.Now;
        while ((DateTime.Now - start).Seconds < 5)
            ;
    }
}

既然前臺線程和後臺線程有這種差別,那麼我們怎麼知道該如何設置一個線程的IsBackground屬性呢?下面是一些基本的原則:對於一些在後臺運行的線程,當程序結束時這些線程沒有必要繼續運行了,那麼這些線程就應該設置爲後臺線程。比如一個程序啓動了一個進行大量運算的線程,可是隻要程序一旦結束,那個線程就失去了繼續存在的意義,那麼那個線程就該是作爲後臺線程的。而對於一些服務於用戶界面的線程往往是要設置爲前臺線程的,因爲即使程序的主線程結束了,其他的用戶界面的線程很可能要繼續存在來顯示相關的信息,所以不能立即終止它們。這裏我只是給出了一些原則,具體到實際的運用往往需要編程者的進一步仔細斟酌。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章