HOW TO:使用執行緒集區 (C# 程式設計手冊)

更新: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

請參閱

工作

監視同步處理技術範例

等候同步處理技術範例

概念

C# 程式設計手冊

監視器

參考

執行緒 (C# 程式設計手冊)

使用執行緒 (C# 程式設計手冊)

Mutex

WaitAll

ManualResetEvent

Set

ThreadPool

QueueUserWorkItem

ManualResetEvent

其他資源

如何使用 Visual C# .NET 或 Visual C# 2005 在多執行緒環境中同步化共用資源的存取

.NET Framework 中的安全性