Windows Runtime 提供現代化線程池 API(Windows.System.Threading 命名空間),取代傳統 System.Threading.ThreadPool。核心類別 ThreadPoolTimer 處理時間觸發工作,ThreadPool 處理佇列工作項。本文詳細解析延遲執行、週期執行、工作項提交與取消機制。
單次觸發,指定延遲時間後執行委派:
var timer = ThreadPoolTimer.CreateTimer(
handler: (timer) => {
// 執行於線程池線程
var result = ComputeHeavy();
// 需更新 UI 時切回 UI 線程
Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
lblResult.Text = result;
});
},
delay: TimeSpan.FromSeconds(3), // 3 秒後觸發
destroyed: (timer) => {
// 計時器銷毀回呼(完成或取消時觸發)
Debug.WriteLine("Timer completed");
}
);
// 取消尚未觸發的計時器
timer.Cancel();
固定間隔重複執行,不保證精確間隔(若上次執行未完成,下次仍會嘗試啟動新線程):
int count = 0;
var periodicTimer = ThreadPoolTimer.CreatePeriodicTimer(
handler: (timer) => {
count++;
Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
lblCount.Text = $"執行次數: {count}";
});
},
period: TimeSpan.FromMilliseconds(100), // 每 100ms 嘗試執行
destroyed: (timer) => {
Debug.WriteLine("Periodic timer destroyed");
}
);
// 停止週期執行
periodicTimer.Cancel();
關鍵特性:
Delay/Period 唯讀屬性可檢視設定值Dispatcher 或 SynchronizationContext 切回 UI 線程var workItem = ThreadPool.RunAsync(
handler: (workItem) => {
// 此處在線程池線程執行
for (int i = 0; i <= 100; i++) {
// 支援取消檢查
if (workItem.Status == AsyncStatus.Canceled) break;
Thread.Sleep(50); // 模擬工作
// 回報進度(需切 UI 線程)
Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
progressBar.Value = i;
});
}
},
priority: WorkItemPriority.High // Low/Normal/High
);
// 完成事件訂閱
workItem.Completed = async (action, status) => {
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
switch (status) {
case AsyncStatus.Completed: lblStatus.Text = "完成"; break;
case AsyncStatus.Canceled: lblStatus.Text = "已取消"; break;
case AsyncStatus.Error: lblStatus.Text = "錯誤"; break;
}
});
};
// 取消工作項
workItem.Cancel();
WorkItemPriority 影響線程池調度順序:
ThreadPool.RunAsync 返回 IAsyncAction,可直接 await:
private async void btnAwaitDemo_Click(object sender, RoutedEventArgs e) {
lblStatus.Text = "執行中...";
string result = await ThreadPool.RunAsync(async (workItem) => {
await Task.Delay(3000); // 非阻塞等待
return "線程池工作完成,已自動切回 UI 線程";
}).AsTask(); // 轉為 Task 以支援 await
lblStatus.Text = result;
}
注意: IAsyncAction 不直接支援 await,需 .AsTask() 轉換(參考前文互轉技術)。
| 維度 | ThreadPoolTimer | ThreadPool.RunAsync |
|---|---|---|
| 觸發方式 | 時間驅動(延遲/週期) | 立即佇列/手動觸發 |
| 適用場景 | 定時輪詢、週期性檢查、延遲初始化 | 背景計算、I/O 操作、長時間任務 |
| 取消機制 | Timer.Cancel() | IAsyncAction.Cancel() + 狀態檢查 |
| 精確度 | 約略(受線程池擁塞影響) | 立即排程,無時間保證 |
| 重複執行 | 內建 PeriodicTimer | 需自行實作循環/遞歸 |
Task.Run + TaskCreationOptions.LongRunning 或自建線程。workItem.Status == AsyncStatus.Canceled,避免資源浪費。Dispatcher.RunAsync,避免跨線程存取 UI 元素例外。Task.Delay 循環模式。Cancel() 所有計時器與工作項,防止記憶體洩漏與存取已釋放 UI 元素。Windows.System.Threading.ThreadPool 為 WinRT 原生 API,返回 IAsyncAction,整合 WinRT 取消/進度/完成模型;System.Threading.ThreadPool 為 .NET 傳統 API,返回 Task,整合 TPL 體系。Windows 8 Store Apps 推薦使用 WinRT 版本,確保與系統資源管理一致。
善用線程池 API,能讓應用程式在保持 UI 高回應性的同時,高效處理背景工作負載。