以下內容部分由 ChatGTP 生成。
以下內容部分來自 Microsoft 官網。
執行緒池是 .NET 重要的非同步觀念,因為這是 async
和 await
底層機制之一。
執行緒池是一種系統管理的執行緒集合,用於有效管理和重用執行緒,以降低頻繁創建和銷毀執行緒的開銷。
.NET 有提供 ThreadPool
使用:
for (int i = 0; i < 100; i++)
{
int j = i;
// 進入非同步任務佇列中;實際上就等同於 Task.Run
ThreadPool.QueueUserWorkItem(async (state) =>
{
//await Task.Delay(5000);
await Task.Delay(Random.Shared.Next(1000, 10000));
System.Console.WriteLine($"第 {j,2} 項結束");
});
}
await Task.Delay(4000);
ThreadPool.GetAvailableThreads(
out var workerThreads,
out var completionPortThreads);
System.Console.WriteLine($"可用工作執行緒數量: {workerThreads}");
System.Console.WriteLine(completionPortThreads);
await Task.Delay(-1);
當呼叫 Task.Run
時,它會將委派的工作項添加到執行緒池的隊列中,並立即返回一個 Task
物件。
執行緒池會在空閒的執行緒中執行此工作,若沒有空閒執行緒,則等待其他任務完成後再執行。
這跟直接創建 Thread
不同,而是將任務丟給 ThreadPool
代為為執行;ThreadPool
據自身狀況提供執行緒來處理任務,因此不會不停的創建 Thread
。
for (int i = 0; i < 1000; i++)
{
// 由 ThreadPool 代為執行
Task.Run(async ()=>{
Thread.Sleep(5000);
System.Console.WriteLine("任務完成");
});
}
Thread.Sleep(-1); // 阻止程式結束
上面這段程式碼不會同時完成這 1000 個任務,而是 ThreadPool
有空閒的執行緒時,才會分配任務執行,所以實際執行會超過 5 秒很多。
可以看見此程式的執行緒最高維持在一定的數量:
ThreadPool
管理著一定數量的 Thread
,以達到不頻繁建立 Thread
的目的;
但問題是,精確計時任務將變得不可靠,由此必須自己建立一個新執行緒:
for (int i = 0; i < 1000; i++)
{
// 創建新執行緒直接執行
new Thread(()=>{
Thread.Sleep(5000);
Console.WriteLine("任務完成");
}).Start();
}
Thread.Sleep(-1); // 阻止程式結束
以上程式碼會讓這 1000 任務幾乎同時完成,因為這是在系統中創建 1000 個執行緒直接執行。
且可以看到程式的執行緒數量已經到達 1000 個: