更新:2007 年 11 月
「執行緒集區」(Thread Pool) 是執行緒的集合,可以用來執行許多幕後工作 (如需背景的詳細資訊,請參閱使用執行緒 (C# 程式設計手冊))。這讓主要執行緒可以同步處理其他工作。
通常是在伺服器應用程式中採用執行緒集區。每個傳入要求都會指派給執行緒集區中的一個執行緒,因此可以同步處理要求,而不用中斷主要執行緒或延遲後續要求的處理。
一旦集區中的執行緒完成工作,就會回到等待中執行緒的佇列,執行緒可以在這裡被重複使用。重覆使用可讓應用程式省去為每個工作建立新執行緒的成本。
執行緒集區通常有執行緒的數目上限。如果所有的執行緒都在忙碌中,多出來的工作會放置在佇列中,直到執行緒可提供服務為止。
您可以實作自己的執行緒集區,但是使用透過 ThreadPool 類別由 .NET Framework 提供的執行緒集區,會容易多了。
下列範例使用 .NET Framework 執行緒集區來計算在 20 和 40 之間,十個數字的 Fibonacci 結果。每個 Fibonacci 結果都由 Fibonacci 類別表示,此類別提供會執行計算且名為 ThreadPoolCallback 的方法。這時會建立表示每個 Fibonacci 值的物件,而且 ThreadPoolCallback 方法會傳遞到 QueueUserWorkItem,這個多載會指派集區中的可用執行緒來執行方法。
因為提供了半隨機值給每個 Fibonacci 物件計算,而且其中每個執行緒都會競爭處理器時間,所以您無法預先知道要花多少時間,才能計算完所有十個結果。這就是在建構期間,ManualResetEvent 類別的執行個體 (Instance) 會傳遞給每個 Fibonacci 物件的原因。每個物件完成計算時,都會傳送所提供事件物件的信號,這樣可讓主要執行緒使用 WaitAll 阻斷執行,直到十個 Fibonacci 物件都計算出結果為止。然後 Main 方法會顯示每個 Fibonacci 結果。
範例
using System;
using System.Threading;
public class Fibonacci
{
public Fibonacci(int n, ManualResetEvent doneEvent)
{
_n = n;
_doneEvent = doneEvent;
}
// Wrapper method for use with thread pool.
public void ThreadPoolCallback(Object threadContext)
{
int threadIndex = (int)threadContext;
Console.WriteLine("thread {0} started...", threadIndex);
_fibOfN = Calculate(_n);
Console.WriteLine("thread {0} result calculated...", threadIndex);
_doneEvent.Set();
}
// Recursive method that calculates the Nth Fibonacci number.
public int Calculate(int n)
{
if (n <= 1)
{
return n;
}
return Calculate(n - 1) + Calculate(n - 2);
}
public int N { get { return _n; } }
private int _n;
public int FibOfN { get { return _fibOfN; } }
private int _fibOfN;
private ManualResetEvent _doneEvent;
}
public class ThreadPoolExample
{
static void Main()
{
const int FibonacciCalculations = 10;
// One event is used for each Fibonacci object
ManualResetEvent[] doneEvents = new ManualResetEvent[FibonacciCalculations];
Fibonacci[] fibArray = new Fibonacci[FibonacciCalculations];
Random r = new Random();
// Configure and launch threads using ThreadPool:
Console.WriteLine("launching {0} tasks...", FibonacciCalculations);
for (int i = 0; i < FibonacciCalculations; i++)
{
doneEvents[i] = new ManualResetEvent(false);
Fibonacci f = new Fibonacci(r.Next(20,40), doneEvents[i]);
fibArray[i] = f;
ThreadPool.QueueUserWorkItem(f.ThreadPoolCallback, i);
}
// Wait for all threads in pool to calculation...
WaitHandle.WaitAll(doneEvents);
Console.WriteLine("All calculations are complete.");
// Display the results...
for (int i= 0; i<FibonacciCalculations; i++)
{
Fibonacci f = fibArray[i];
Console.WriteLine("Fibonacci({0}) = {1}", f.N, f.FibOfN);
}
}
}
輸出如下:
launching 10 tasks...
result calculated...
result calculated...
result calculated...
result calculated...
result calculated...
result calculated...
result calculated...
result calculated...
result calculated...
result calculated...
all calculations complete
Fibonacci(22) = 17711
Fibonacci(25) = 75025
Fibonacci(32) = 2178309
Fibonacci(36) = 14930352
Fibonacci(32) = 2178309
Fibonacci(26) = 121393
Fibonacci(35) = 9227465
Fibonacci(23) = 28657
Fibonacci(39) = 63245986
Fibonacci(22) = 17711