一、兩類適用 ThreadPool/Timer 的場景
| 場景 | 特徵 | 解決方案 |
| 大量等待事件 | 執行緒多數時間阻塞等待 I/O、訊號 | ThreadPool:佇列工作項,系統自動管理執行緒 |
| 週期性喚醒 | 執行緒長期睡眠,定時檢查/執行 | Timer:指定間隔觸發回呼,專用執行緒 |
二、ThreadPool 核心機制
QueueUserWorkItem 多載
ThreadPool.QueueUserWorkItem(WaitCallback callback);
ThreadPool.QueueUserWorkItem(WaitCallback callback, object state);
// WaitCallback = void Method(object state)
- 靜態類別,不可實例化
- 工作項一旦佇列無法取消
- 需 Windows 2000+ (API 相依)
- 系統自動建立/管理/銷毀執行緒
ManualResetEvent:手動重置訊號旗標
Set():發送訊號,釋放所有等待執行緒
Reset():清除訊號
WaitOne():阻塞直到有訊號
- 初始狀態可指定
三、完整 ThreadPool 範例程式碼
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:");
bool w2k = false;
const int MaxCount = 10;
var eventX = new ManualResetEvent(false);
Console.WriteLine($"Queuing {MaxCount} items to Thread Pool");
var alpha = new Alpha(MaxCount) { EventX = eventX };
try
{
ThreadPool.QueueUserWorkItem(new WaitCallback(alpha.Beta), new SomeState(0));
w2k = true;
}
catch (NotSupportedException)
{
Console.WriteLine("These API's may fail when called on a non-Windows 2000 system.");
w2k = false;
}
if (w2k)
{
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)");
Console.WriteLine("\nLoad across threads");
foreach (object k in alpha.HashCount.Keys)
Console.WriteLine($"{k} {alpha.HashCount[k]}");
}
Console.ReadLine();
return 0;
}
}
四、Timer 基礎架構
TimerCallback 委托
TimerCallback callback = new TimerCallback(CheckStatus);
// void CheckStatus(object state)
建立 Timer
Timer timer = new Timer(callback, state, 1000, 1000);
// 1秒後首次觸發,之後每1秒觸發
五、ThreadPool vs Timer 選擇指南
| 決策因素 | 選 ThreadPool | 選 Timer |
| 觸發方式 | 外部事件/佇列 | 時間間隔 |
| 執行頻率 | 爆發/不規則 | 固定週期 |
| 狀態管理 | 每項獨立 state | 共享單一 state |
| 精度要求 | 無 | 毫秒級 |
六、系統需求與例外處理
ThreadPool 依賴 Win2000+ API,舊系統可能擲 NotSupportedException
- 生產代碼應捕獲並降級(如改用專用執行緒)
總結
ThreadPool 將「工作項佇列」與「執行緒管理」解耦,Timer 將「時間觸發」與「工作執行」解耦。兩者配合 ManualResetEvent、Interlocked 等同步原語,構成 .NET 早期多執行緒自動化管理的基石。現代開發請遷移至 Task、Timer (配合 async)、BackgroundService 等更高階抽象。