類別 System.Threading.ThreadPool 會提供由系統管理的背景工作線程集區,讓您專注於應用程式工作,而不是線程管理。 如果您有需要背景處理的簡短工作,受控線程集區是利用多個線程的簡單方式。 在 Framework 4 和更新版本中,線程集區的使用相當容易,因為您可以建立 Task 和 Task<TResult> 對象,在線程集區線程上執行異步工作。
.NET 會針對許多用途使用線程集區線程,包括 工作平行連結庫 (TPL) 作業、異步 I/O 完成、 定時器 回呼、已註冊的等候作業、使用委派的異步方法呼叫,以及 System.Net 套接字聯機。
線程集區特性
執行緒池的執行緒是背景執行緒。 每個線程都會使用預設堆疊大小、以預設優先順序執行,且位於多線程 Apartment 中。 線程集區中的執行緒完成其工作之後,就會返回到等候執行緒的隊列。 從此刻起,即可重複使用。 此重複使用可讓應用程式避免為每個工作建立新線程的成本。
每個進程只有一個線程集區。
線程集區線程中的例外狀況
線程集區線程中未處理的例外狀況會終止進程。 此規則有三個例外狀況:
- 因為呼叫了System.Threading.ThreadAbortException,所以在執行緒池的執行緒中拋出了Thread.Abort。
- System.AppDomainUnloadedException因為正在卸載應用程式域,會從線程池中的執行緒拋出。
- 公共語言執行環境或主機程序會終止執行緒。
如需詳細資訊,請參閱 Managed線程中的例外狀況。
線程集區線程數目上限
可以排入線程集區的作業數目只受限於可用的記憶體。 不過,線程集區會限制進程同時作用中的線程數目。 當執行緒池中的所有執行緒都在忙碌時,其他工作項目會排入佇列,然後再等到有可用的執行緒來執行這些項目。 進程線程集區的預設大小取決於數個因素,例如虛擬位址空間的大小。 進程可以呼叫 ThreadPool.GetMaxThreads 方法來判斷線程數目。
您可以使用 ThreadPool.GetMaxThreads 和 ThreadPool.SetMaxThreads 方法來控制最大線程數目。
備註
裝載通用語言運行庫的代碼可以使用 ICorThreadpool::CorSetMaxThreads
方法來設定大小。
線程集區最小值
線程集區會視需要提供新的工作執行緒或 I/O 完成執行緒,直到達到每個類別的指定最小值為止。 您可以使用 ThreadPool.GetMinThreads 方法來取得這些最小值。
備註
當需求很低時,線程集區線程的實際數目可能會低於最小值。
達到最小值時,線程集區可以建立其他線程,或等到某些工作完成為止。 執行緒池會建立並銷毀工作執行緒,以優化輸送量,其定義為每單位時間完成的任務數量。 線程太少可能無法充分利用可用的資源,而太多線程可能會增加資源爭用。
謹慎
您可以使用 ThreadPool.SetMinThreads 方法來增加閑置線程數目下限。 不過,不必要地增加這些值可能會導致效能問題。 如果同時啟動太多任務,則所有工作可能看起來都很慢。 在大部分情況下,線程集區會使用自己的演算法來更好地配置線程。
使用執行緒池
使用線程集區最簡單的方式是使用 工作平行連結庫 (TPL) 。 根據預設,像 Task 和 Task<TResult> 這樣的 TPL 類型會使用線程集區線程來執行任務。
您也可以從受管理代碼中呼叫 ThreadPool.QueueUserWorkItem (或從非受管理代碼中呼叫 ICorThreadpool::CorQueueUserWorkItem
),並傳遞 System.Threading.WaitCallback 這個代表執行工作方法的委派,以使用執行緒池。
另一種使用線程集區的方法,是使用 ThreadPool.RegisterWaitForSingleObject 方法將與等候作業相關的工作專案排入佇列,並在 System.Threading.WaitHandle 發出訊號或逾時時,呼叫由委派 System.Threading.WaitOrTimerCallback 所代表的方法。 線程集區線程可用來叫用回呼方法。
如需範例,請檢查參考的 API 頁面。
略過安全性檢查
線程集區也提供 ThreadPool.UnsafeQueueUserWorkItem 和 ThreadPool.UnsafeRegisterWaitForSingleObject 方法。 僅在您確定呼叫端的堆疊不會影響佇列任務執行期間的任何安全檢查時,才使用這些方法。 ThreadPool.QueueUserWorkItem 和 ThreadPool.RegisterWaitForSingleObject 兩者都會擷取呼叫端的堆疊,當執行緒開始執行工作時,會將這些堆疊合併到執行緒集區的執行緒堆疊中。 如果需要安全性檢查,則必須檢查整個堆疊。 雖然檢查提供安全性,但它也有效能成本。
不使用線程集區線程的時機
有幾個適合的情境,有必要自己建立和管理執行緒,而不是使用執行緒集區:
- 您需要前景線程。
- 您需要將線程設置為特定的優先級。
- 您有會導致線程長時間封鎖的任務。 線程集區有線程數目上限,因此大量的封鎖線程集區線程可能會防止工作啟動。
- 您需要將線程放入單一執行緒單元中。 所有 ThreadPool 線程都在多執行緒 Apartment 模型中。
- 您需要有與執行緒相關聯的穩定身份,或將執行緒專門用於某個任務。