﻿# 使用 ThreadPool 時應注意預設同時執行的 Thread 數量

之前我們有個專案需要透過 Console Application (指令列程式) 解析上萬個檔案，而且每解析一個檔案就必須要啟動這個程式一次，為了縮短程式執行的時間，我們當時就採用 [ThreadPool](http://msdn.microsoft.com/zh-tw/library/system.threading.threadpool\(VS.80\).aspx) 技術進行開發，結果最近客戶購買了新主機，安裝了我們的程式後卻發現經常還沒跑完就死了，研究了好一番功夫才發現問題出在 .NET 2.0 預設的 Thread 數量變了。

我們當時使用了 [ThreadPool](http://msdn.microsoft.com/zh-tw/library/system.threading.threadpool\(VS.80\).aspx) 且並沒有透過 [ThreadPool.SetMaxThreads](http://msdn.microsoft.com/zh-tw/library/system.threading.threadpool.setmaxthreads\(VS.80\).aspx) 設定同時執行的 Threads 上限，當時的電腦是單 CPU + 單核心，因此程式執行的相安無事。

經[查詢資料](http://www.bluebytesoftware.com/blog/PermaLink,guid,ca22a5a8-a3c9-4ee8-9b41-667dbd7d2108.aspx)得知，在 .NET 2.0 SP1 之前，每個 CPU 或每個核心(Core)預設 ThreadPool 的同時執行緒上限是 25 個 Threads，但在 .NET 2.0 SP1 以後卻調整到 250 個 Threads，這是個很大的差別，以致於我們一個程式中同時開啟太多個 Console Application，超出了系統可接受的上限，所以許多程式都沒有執行完就自動結束了，況且客戶的新電腦是雙 CPU + 四核心，你可想見程式不出問題也難！

最後，我們利用 [ThreadPool.SetMaxThreads](http://msdn.microsoft.com/zh-tw/library/system.threading.threadpool.setmaxthreads\(VS.80\).aspx) 這個靜態方法設定同時執行的 Threads 上限，這個問題就迎刃而解：

```csharp
// 設定最大同時執行的 Thread 數量
ThreadPool.SetMaxThreads(10, 10);
```

\---

另外提及一點，在 MSDN 上的 ThreadPool 的說明文件，[繁體中文版](http://msdn.microsoft.com/zh-tw/library/system.threading.threadpool.aspx) 與 [英文版](http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx) 的內容是不一致的：

英文版的 [ThreadPool Class](http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx) 中提及同時執行 Threads 上限的說明文字如下：

> There is one thread pool per process. The thread pool has a default size of 250 worker threads per available processor, and 1000 I/O completion threads. The number of threads in the thread pool can be changed by using the [SetMaxThreads](http://msdn.microsoft.com/en-us/library/system.threading.threadpool.setmaxthreads.aspx) method. Each thread uses the default stack size and runs at the default priority.

中文版的 [ThreadPool 類別](http://msdn.microsoft.com/zh-tw/library/system.threading.threadpool.aspx) 中提及同時執行 Threads 上限的說明文字如下：

> 每一個處理序都會有一個執行緒集區。執行緒集區的預設大小為每個可用處理器 25 個背景工作執行緒，以及 1000 個 I/O 完成執行緒。您可以使用 [SetMaxThreads](http://msdn.microsoft.com/zh-tw/library/system.threading.threadpool.setmaxthreads.aspx) 方法變更執行緒集區中的執行緒數目。每個執行緒都使用預設的堆疊大小，並且按照預設的優先權來執行。

我個人是覺得可能是因為翻譯的關係，當英文版文件修訂的時候其他國家翻譯文件不見得能夠立即更新，如果單單查閱中文版的 MSDN 文件也是有可能會吸收到錯誤的資訊。

**相關連結**

-   [Why the CLR 2.0 SP1's threadpool default max thread count was increased to 250/CPU](http://www.bluebytesoftware.com/blog/2007/03/05/WhyTheCLR20SP1sThreadpoolDefaultMaxThreadCountWasIncreasedTo250CPU.aspx)
-   [ThreadPool Class](http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx)  /  [ThreadPool 類別](http://msdn.microsoft.com/zh-tw/library/system.threading.threadpool.aspx)
