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

C# 多執行緒機制探索(10):ThreadPool 執行緒池與 Timer 定時器自動化管理完整實戰

     編輯:關於C語言

一、ThreadPool:工作項佇列與自動執行緒管理

適用場景:大量短暫工作、等待 I/O、不需精確控制執行緒生命週期。CLR 內建執行緒池,自動調整執行緒數量(最小/最大閾值)。

二、ThreadPool 核心 API


// 佇列工作項
ThreadPool.QueueUserWorkItem(WaitCallback callback);
ThreadPool.QueueUserWorkItem(WaitCallback callback, object state);

// 設定執行緒池大小(.NET Core/5+ 建議勿手動調整)
ThreadPool.SetMinThreads(worker, io);
ThreadPool.SetMaxThreads(worker, io);
ThreadPool.GetAvailableThreads(out worker, out io);

三、完整範例:佇列 10 項工作與 ManualResetEvent 同步


using System;
using System.Collections;
using System.Threading;

public class SomeState
{
    public int Cookie;
    public SomeState(int cookie) { Cookie = cookie; }
}

public class Alpha
{
    public Hashtable HashCount = new Hashtable();
    public ManualResetEvent EventX;
    public static int Count, MaxCount;

    public Alpha(int max) { MaxCount = max; }

    public void Beta(object state)
    {
        var s = (SomeState)state;
        Console.WriteLine($" {Thread.CurrentThread.GetHashCode()} {s.Cookie} :");
        Console.WriteLine($"HashCount.Count=={HashCount.Count}, Thread.HashCode=={Thread.CurrentThread.GetHashCode()}");

        lock (HashCount)
        {
            int key = Thread.CurrentThread.GetHashCode();
            if (!HashCount.ContainsKey(key)) HashCount[key] = 0;
            HashCount[key] = (int)HashCount[key] + 1;
        }
        Thread.Sleep(2000);
        if (Interlocked.Increment(ref Count) == MaxCount)
        {
            Console.WriteLine("\nSetting eventX");
            EventX.Set();
        }
    }
}

public class SimplePool
{
    public static int Main()
    {
        Console.WriteLine("Thread Pool Sample:");
        const int MaxCount = 10;
        var eventX = new ManualResetEvent(false);
        Console.WriteLine($"Queuing {MaxCount} items to Thread Pool");

        var alpha = new Alpha(MaxCount) { EventX = eventX };
        ThreadPool.QueueUserWorkItem(new WaitCallback(alpha.Beta), new SomeState(0));

        for (int i = 1; i < MaxCount; i++)
        {
            Console.WriteLine($"Queue to Thread Pool {i}");
            ThreadPool.QueueUserWorkItem(new WaitCallback(alpha.Beta), new SomeState(i));
        }

        Console.WriteLine("Waiting for Thread Pool to drain");
        eventX.WaitOne(Timeout.Infinite, true);
        Console.WriteLine("Thread Pool has been drained (Event fired)\nLoad across threads");
        foreach (object k in alpha.HashCount.Keys)
            Console.WriteLine($"{k} {alpha.HashCount[k]}");
        Console.ReadLine();
        return 0;
    }
}

ThreadPool與Timer輸出

四、關鍵類別解析

類別用途
SomeState封裝傳遞給工作項的資料
ManualResetEvent訊號旗標:Set() 釋放所有等待者,WaitOne() 阻塞直到訊號
Interlocked.Increment原子遞增,無需 lock
WaitCallback委托簽名 void Callback(object state)

五、Timer:定時/週期性執行工作

適用場景:週期性檢查、定時清理、排程任務。建立時指定 TimerCallback 委托、狀態物件、延遲、間隔。

完整範例


using System;
using System.Threading;

class TimerExampleState
{
    public int Counter;
    public Timer Timer;
}

class App
{
    public static void Main()
    {
        var s = new TimerExampleState();
        TimerCallback callback = CheckStatus;
        Timer timer = new Timer(callback, s, 1000, 1000); // 1秒後開始,每1秒執行
        s.Timer = timer;

        while (s.Timer != null) Thread.Sleep(0); // 主執行緒等待
        Console.WriteLine("Timer example done.");
        Console.ReadLine();
    }

    static void CheckStatus(object state)
    {
        var s = (TimerExampleState)state;
        s.Counter++;
        Console.WriteLine($"{DateTime.Now.TimeOfDay} Checking Status {s.Counter}.");

        if (s.Counter == 5)
        {
            s.Timer.Change(10000, 2000); // 10秒後重啟,間隔改2秒
            Console.WriteLine("changed...");
        }
        if (s.Counter == 10)
        {
            Console.WriteLine("disposing of timer...");
            s.Timer.Dispose();
            s.Timer = null; // 主執行緒循環結束條件
        }
    }
}

六、Timer 核心方法

方法說明
Change(dueTime, period)動態修改延遲與間隔(-1 表示停用)
Dispose()釋放定時器資源,停止觸發

七、ThreadPool vs Timer vs Task 比較

特性ThreadPoolTimerTask / Task.Run
適用火後不顧工作項週期性/定時觸發現代非同步、可組合、支援 await
回傳值無無Task<T>
異常處理難捕捉難捕捉自然傳播
取消不支援DisposeCancellationToken
排程精度無毫秒級配合 Timer/Task.Delay

八、現代最佳實務

  1. 新代碼優先用 Task.Run、async/await
  2. CPU 密集長時間工作:Task.Run + 自訂 TaskScheduler 或專用執行緒
  3. 定時任務:System.Threading.Timer 或 Microsoft.Extensions.Hosting.BackgroundService
  4. 避免直接操作 ThreadPool:除非極端效能調校
  5. Interlocked 仍是無鎖計數器首選

總結

ThreadPool 自動化管理大量短暫工作項,Timer 提供定時/週期觸發能力。兩者結合 ManualResetEvent、Interlocked 可構建完整的背景處理管線。現代 .NET 開發應以 Task、async/await、Channels、BackgroundService 為主,僅在相容舊代碼或極端效能場景直接使用 ThreadPool/Timer。

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