C#多執行緒學習(二) 如何操縱一個執行緒

瞌睡的小牛發表於2023-04-19

C#多執行緒學習(二) 如何操縱一個執行緒

執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念

下面我們就動手來建立一個執行緒,使用Thread類建立執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒幹什麼事)

在C#中,執行緒入口是透過ThreadStart代理(delegate)來提供的,你可以把ThreadStart理解為一個函式指標,指向執行緒要執行的函式,當呼叫Thread.Start()方法後,執行緒就開始執行ThreadStart所代表或者說指向的函式。開啟你的VS.net,新建一個控制檯應用程式(Console Application),編寫完全控制一個執行緒的程式碼示例:

//ThreadTest.cs
using System;
using System.Threading;
namespace ThreadTest
{
    public class Alpha
    {
        public void Beta()
        {
            while (true)
            {
                Console.WriteLine("Alpha.Beta is running in its own thread.");
            }
        }
    };
    public class Simple
    {
        public static int Main()
        {
            Console.WriteLine("Thread Start/Stop/Join Sample");
            Alpha oAlpha = new Alpha();
            file://這裡建立一個執行緒,使之執行Alpha類的Beta()方法
            Thread oThread = new Thread(new ThreadStart(oAlpha.Beta));
            oThread.Start();
            while (!oThread.IsAlive)
                Thread.Sleep(1);
            oThread.Abort();
            oThread.Join();
            Console.WriteLine();
            Console.WriteLine("Alpha.Beta has finished");
            try
            {
                Console.WriteLine("Try to restart the Alpha.Beta thread");
                oThread.Start();
            }
            catch (ThreadStateException)
            {
                Console.Write("ThreadStateException trying to restart Alpha.Beta.");
                Console.WriteLine("Expected since aborted threads cannot be restarted.");
                Console.ReadLine();
            }
            return 0;
        }
    }
}

這段程式包含兩個類Alpha和Simple,在建立執行緒oThread時我們用指向Alpha.Beta()方法的初始化了ThreadStart代理(delegate)物件,當我們建立的執行緒oThread呼叫oThread.Start()方法啟動時,實際上程式執行的是Alpha.Beta()方法:

Alpha oAlpha = new Alpha();
Thread oThread = new Thread(new ThreadStart(oAlpha.Beta));
oThread.Start();

然後在Main()函式的while迴圈中,我們使用靜態方法Thread.Sleep()讓主執行緒停了1ms,這段時間CPU轉向執行執行緒oThread。然後我們試圖用Thread.Abort()方法終止執行緒oThread,注意後面的oThread.Join(),Thread.Join()方法使主執行緒等待,直到oThread執行緒結束。你可以給Thread.Join()方法指定一個int型的引數作為等待的最長時間。之後,我們試圖用Thread.Start()方法重新啟動執行緒oThread,但是顯然Abort()方法帶來的後果是不可恢復的終止執行緒,所以最後程式會丟擲ThreadStateException異常。

主執行緒Main()函式

所有執行緒都是依附於Main()函式所在的執行緒的,Main()函式是C#程式的入口,起始執行緒可以稱之為主執行緒。
如果所有的前臺執行緒都停止了,那麼主執行緒可以終止,而所有的後臺執行緒都將無條件終止。
所有的執行緒雖然在微觀上是序列執行的,但是在宏觀上你完全可以認為它們在並行執行。

Thread.ThreadState 屬性

這個屬性代表了執行緒執行時狀態,在不同的情況下有不同的值,我們有時候可以透過對該值的判斷來設計程式流程。
ThreadState 屬性的取值如下:
Aborted:執行緒已停止;
AbortRequested:執行緒的Thread.Abort()方法已被呼叫,但是執行緒還未停止;
Background:執行緒在後臺執行,與屬性Thread.IsBackground有關;
Running:執行緒正在正常執行;
Stopped:執行緒已經被停止;
StopRequested:執行緒正在被要求停止;
Suspended:執行緒已經被掛起(此狀態下,可以透過呼叫Resume()方法重新執行);
SuspendRequested:執行緒正在要求被掛起,但是未來得及響應;
Unstarted:未呼叫Thread.Start()開始執行緒的執行;
WaitSleepJoin:執行緒因為呼叫了Wait(),Sleep()或Join()等方法處於封鎖狀態;

上面提到了Background狀態表示該執行緒在後臺執行,那麼後臺執行的執行緒有什麼特別的地方呢?其實後臺執行緒跟前臺執行緒只有一個區別,那就是後臺執行緒不妨礙程式的終止。一旦一個程式所有的前臺執行緒都終止後,CLR(通用語言執行環境)將透過呼叫任意一個存活中的後臺程式的Abort()方法來徹底終止程式。

執行緒的優先順序

當執行緒之間爭奪CPU時間時,CPU 是按照執行緒的優先順序給予服務的。在C#應用程式中,使用者可以設定 5 個不同的優先順序,由高到低分別是Highest,AboveNormal,Normal,BelowNormal,Lowest,在建立執行緒時如果不指定優先順序,那麼系統預設為ThreadPriority.Normal。

給一個執行緒指定優先順序,我們可以使用如下程式碼:

//設定優先順序為最低
myThread.Priority = ThreadPriority.Lowest;

透過設定執行緒的優先順序,我們可以安排一些相對重要的執行緒優先執行,例如對使用者的響應等等。

相關文章