首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 多執行緒基礎操作:Thread 類別建立、啟動、終止、Join、狀態與優先級完整指南

     編輯:關於C#

前言

System.Threading.Thread 是 .NET 中**手動建立與控制執行緒**的核心類別。雖然現代開發推薦使用 Task、ThreadPool、async/await 等高階抽象,但理解 Thread 的生命週期、狀態機制、優先級、同步方法 (Join、Sleep、Abort、Interrupt) 仍是掌握多執行緒本質、除錯複雜並發問題、維護舊版程式碼的必要基礎。本文將完整解析 Thread 的建立方式、ThreadStart 委派、啟動與終止流程、主執行緒關係、ThreadState 狀態列舉、優先級設定,並提供完整可執行範例。

建立與啟動執行緒

ThreadStart 委派

Thread 建構函式接受 ThreadStart 委派 (無參數、無回傳值) 或 ParameterizedThreadStart (單一 object 參數):

// 無參數版本
public delegate void ThreadStart();

// 有參數版本 (需轉型)
public delegate void ParameterizedThreadStart(object obj);

基本建立與啟動範例

using System;
using System.Threading;

namespace ThreadBasicDemo
{
    class Worker
    {
        public void DoWork()
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine($"[Worker] 執行中... {i} (ThreadId: {Thread.CurrentThread.ManagedThreadId})");
                Thread.Sleep(500);
            }
        }
    }

    class Program
    {
        static void Main()
        {
            Console.WriteLine($"[Main] 主執行緒啟動 (ThreadId: {Thread.CurrentThread.ManagedThreadId})");

            var worker = new Worker();

            // 1. 建立執行緒,指定入口方法
            Thread t = new Thread(worker.DoWork); // 隱含轉換為 ThreadStart

            // 2. 設定執行緒屬性 (可選)
            t.Name = "MyWorkerThread";
            t.IsBackground = false; // 前景執行緒:會阻止程式結束

            // 3. 啟動執行緒
            t.Start();

            // 4. 主執行緒等待子執行緒啟動 (確保 IsAlive 為 true)
            while (!t.IsAlive) Thread.Sleep(1);

            Console.WriteLine($"[Main] 子執行緒已啟動,狀態: {t.ThreadState}");

            // 5. 等待子執行緒結束 (Join)
            t.Join(); // 無限期等待;也可 t.Join(TimeSpan) 設定逾時

            Console.WriteLine("[Main] 子執行緒已結束,主執行緒繼續。");
            Console.ReadKey();
        }
    }
}

執行緒終止方式比較

方法機制特點建議
自然結束入口方法執行完畢返回最安全、資源正常釋放、finally 區塊執行首選:設計可結束的迴圈條件 (如 CancellationToken、volatile bool 旗標)
Abort()擲出 ThreadAbortException 強制中止已淘汰 (.NET Core 不支援)、不可預測、可能損毀資料、finally 仍執行但 ResetAbort 可阻止嚴禁使用,舊版相容性除外
Interrupt()在執行緒處於 WaitSleepJoin 狀態時擲出 ThreadInterruptedException僅能中斷阻塞中執行緒 (Sleep、Join、Wait);執行中程式碼不受影響輔助手段,配合 try-catch 處理

正確的取消模式:CancellationToken (.NET 4.0+)

var cts = new CancellationTokenSource();
Thread t = new Thread(() => DoWork(cts.Token));
t.Start();

// ... 某時刻要求取消
cts.Cancel(); // 發出取消信號

void DoWork(CancellationToken token)
{
    while (!token.IsCancellationRequested)
    {
        // 工作邏輯
        token.ThrowIfCancellationRequested(); // 或手動檢查 token.IsCancellationRequested
    }
}

Thread.Join:等待執行緒結束

  • t.Join():無限期阻塞呼叫執行緒,直到 t 結束。
  • t.Join(TimeSpan timeout) / t.Join(int millisecondsTimeout):等待指定時間,逾時回傳 false,執行緒仍在執行回傳 true。
  • **避免死結**:若執行緒 A Join 執行緒 B,而 B 又嘗試 Join A 或鎖定 A 持有的資源,將發生死結。

Thread.ThreadState 屬性:執行緒狀態機

ThreadState 為 Flags 屬性 (可組合),常見值:

狀態判斷範例

if ((t.ThreadState & ThreadState.Running) != 0) 
    Console.WriteLine("執行中");

if ((t.ThreadState & (ThreadState.Stopped | ThreadState.Aborted)) != 0)
    Console.WriteLine("已結束");

前景 vs 背景執行緒

狀態值說明
Unstarted尚未呼叫 Start()
Running正常執行中
WaitSleepJoin阻塞於 Wait、Sleep、Join
Suspended已呼叫 Suspend() (已淘汰)
SuspendRequested要求暫停但尚未生效 (已淘汰)
AbortRequested已呼叫 Abort() 但尚未終止
Stopped / Aborted已結束 (正常或被中止)
Background標記為背景執行緒 (非獨立狀態,配合 IsBackground 屬性)

執行緒優先級

Thread.Priority (五級):Highest > AboveNormal > Normal (預設) > BelowNormal > Lowest。

  • 排程器傾向分配更多 CPU 時間給高優先級執行緒,但**非絕對保證**。
  • 濫用高優先級會導致低優先級**餓死**。
  • 實務建議:極少調整優先級,預設 Normal 即可滿足絕大多數需求。

完整範例:展示啟動、狀態、Join、優先級、背景執行緒行為

using System;
using System.Threading;

namespace ThreadComprehensiveDemo
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine($"[Main] 主執行緒 ID: {Thread.CurrentThread.ManagedThreadId}");

            // 1. 前景執行緒:會阻止程式結束
            Thread fg = new Thread(ForegroundWork) { Name = "Foreground", IsBackground = false };
            fg.Start();

            // 2. 背景執行緒:不阻止程式結束
            Thread bg = new Thread(BackgroundWork) { Name = "Background", IsBackground = true };
            bg.Start();

            // 3. 觀察狀態變化
            Thread.Sleep(100);
            Console.WriteLine($"[Main] fg.State={fg.ThreadState}, bg.State={bg.ThreadState}");

            // 4. 等待前景執行緒 (主執行緒會卡住直到 fg 結束)
            Console.WriteLine("[Main] 等待前景執行緒結束 (Join)...");
            fg.Join();
            Console.WriteLine("[Main] 前景執行緒已結束。");

            // 5. 此時背景執行緒可能仍在執行,但主執行緒結束 → 程式結束 → 背景執行緒被強制終止
            Console.WriteLine("[Main] 主執行緒即將結束,背景執行緒將被強制終止。");
            // bg.Join(); // 若取消註解,程式會等待背景執行緒完成

            Console.ReadKey(); // 僅為保持主控台開啟
        }

        static void ForegroundWork()
        {
            for (int i = 0; i < 3; i++)
            {
                Console.WriteLine($"[Foreground] 工作 {i}");
                Thread.Sleep(1000);
            }
        }

        static void BackgroundWork()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine($"[Background] 工作 {i}");
                Thread.Sleep(500);
            }
        }
    }
}

Thread vs Task vs ThreadPool 選擇指南

特性前景執行緒 (IsBackground=false)背景執行緒 (IsBackground=true)
預設值手動建立的 Thread 預設為前景ThreadPool、Task 預設為背景
程式結束條件**所有前景執行緒結束** → 程式結束 (CLR 強制終止所有背景執行緒)不阻止程式結束
適用場景關鍵業務邏輯、必須完成的工作輔助工作、監聽、快取清理、非關鍵批次
需求推薦方案理由
現代非同步程式設計、回傳值、續作、取消、異常處理Task.Run / async/await語法簡潔、組合性強、預設用 ThreadPool、支援 CancellationToken
火燒忘背景工作、無回傳值、舊版相容ThreadPool.QueueUserWorkItem輕量、無 Task 物件開銷
需精細控制:名稱、優先級、IsBackground、單一實例、長時間運行new Thread(...)完整控制執行緒屬性與生命週期
STA 單元執行緒 (COM、UI、Clipboard)new Thread(() => { ... }) { ApartmentState = ApartmentState.STA }.Start()Task 預設 MTA,無法直接設定 STA
需自訂排程器、長時間 CPU 密集工作不佔用 ThreadPoolTask.Factory.StartNew(..., TaskCreationOptions.LongRunning)建立專用執行緒,不影響 ThreadPool 可用度

總結

Thread 類別提供了對作業系統執行緒最直接的控制能力:建立、啟動、命名、優先級、前景/背景模式、Join 等待、Sleep 讓步、Interrupt 中斷阻塞、ThreadState 狀態觀察。雖然現代 .NET 開發**強烈建議優先使用 Task / async/await**,但深入理解 Thread 機制對於:除錯死結/競爭條件、維護舊版程式碼、實作 STA 需求、自訂排程器、理解 ThreadPool/Task 底層運作,具有不可替代的價值。核心原則:**避免使用 Abort/Suspend/Resume、善用 CancellationToken 取消、最小化共享狀態、優先使用高階抽象**。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved