共用方式為


線程集區

線程集區是背景工作線程的集合,可有效率地代表應用程式執行異步回呼。 線程集區主要用於減少應用程式線程數目,並提供背景工作線程的管理。 應用程式可以將工作專案排入佇列、將工作與可等候的句柄產生關聯、根據定時器自動排入佇列,以及與 I/O 系結。

線程集區架構

下列應用程式可以受益於使用線程集區:

  • 高度平行且可以異步分派大量小型工作專案的應用程式(例如分散式索引搜尋或網路 I/O)。
  • 建立並終結大量線程的應用程式,每個線程會執行一小段時間。 使用線程集區可以降低線程管理的複雜度,以及線程建立和解構所涉及的額外負荷。
  • 在背景和平行處理獨立工作專案的應用程式(例如載入多個索引標籤)。
  • 應用程式,必須在核心對象上執行獨佔等候,或封鎖物件上的傳入事件。 使用線程集區可減少線程管理的複雜性,並藉由減少內容交換器數目來提升效能。
  • 建立自定義等候程式線程以等候事件的應用程式。

原始線程集區已在 Windows Vista 中完全重新架構。 新的線程集區已改善,因為它提供單一背景工作線程類型(同時支援 I/O 和非 I/O)、不使用定時器線程、提供單一定時器佇列,並提供專用的持續性線程。 它也提供清除群組、更高的效能、每個個別排程的多個集區,以及新的線程集區 API。

線程集區架構包含下列各項:

  • 執行回呼函式的背景工作線程
  • 等候多個等候句柄的等候者線程
  • 工作佇列
  • 每個進程的預設線程集區
  • 管理背景工作線程的背景工作處理站

最佳做法

新的 線程集區 API 提供比 原始線程集區 API 更多的彈性和控制。 然而,有一些微妙但重要的差異。 在原始 API 中,等候重設是自動的;在新 API 中,每次都必須明確重設等候。 原始 API 會自動處理模擬,並將呼叫進程的安全性內容傳送至線程。 使用新的 API 時,應用程式必須明確設定安全性內容。

以下是使用線程集區時的最佳做法:

  • 進程的線程會共用線程集區。 單一背景工作線程可以一次執行多個回呼函式。 這些背景工作線程是由線程集區所管理。 因此,請勿在線程上呼叫 TerminateThread,或從回調函式呼叫 ExitThread,以終止線程集區中的線程。

  • I/O 要求可以在線程集區中的任何線程上執行。 取消線程集區線程上的 I/O 需要同步處理,因為 cancel 函式可能會在處理 I/O 要求的不同線程上執行,這可能會導致取消未知的作業。 若要避免這種情況,請一律提供在呼叫 CancelIoEx 進行異步 I/O 時起始 I/O 要求的重疊結構,或使用您自己的同步處理來確保在呼叫 CancelSynchronousIo 或 CancelIoEx 函式之前,在目標線程上無法啟動任何其他 I/O。

  • 先清除回呼函式中建立的所有資源,再從函式傳回。 其中包括 TLS、安全性內容、線程優先順序和 COM 註冊。 回呼函式也必須在傳回之前還原線程狀態。

  • 讓等候句柄及其相關聯的物件保持運作,直到線程集區已發出信號,該句柄已完成為止。

  • 標示等候冗長作業的所有線程(例如 I/O 排清或資源清除),讓線程集區可以配置新的線程,而不是等待這個線程。

  • 卸除使用線程集區的 DLL 之前,請先取消所有工作專案、I/O、等候作業和定時器,然後等候執行回呼來完成。

  • 藉由消除工作專案與回呼之間的相依性,確保回呼不會等待自己完成,以及保留線程優先順序,以避免死結。

  • 請勿使用預設線程集區,將進程中太多專案排入太快的佇列。 每個進程都有一個預設線程集區,包括Svchost.exe。 根據預設,每個線程集區最多有500個背景工作線程。 當處於就緒/執行中狀態的背景工作線程數目必須小於處理器數目時,線程集區會嘗試建立更多背景工作線程。

  • 避免 COM 單個線程 Apartment 模型,因為它與線程集區不相容。 STA 會建立可能會影響線程下一個工作項目的線程狀態。 STA 通常壽命很長,而且具有線程親和性,這與線程集區相反。

  • 建立新的線程集區來控制線程優先順序和隔離、建立自定義特性,並可能改善回應性。 不過,其他線程集區需要更多系統資源(線程、核心記憶體)。 太多集區會增加 CPU 爭用的可能性。

  • 可能的話,請使用可等候的物件,而不是以APC為基礎的機制來發出線程集區線程的訊號。 APC 不適用於線程集區線程,因為系統控制線程集區線程的存留期,因此線程可以在傳遞通知之前終止。

  • 使用線程集區調試程式延伸模組 !tp。 此指令具有下列用法:

    • 集區位址旗標
    • obj 位址旗標
    • tqueue 位址旗標
    • waiter 位址
    • 背景工作 位址

    如果位址為零,則針對集區、服務員和背景工作角色,命令會傾印所有物件。 對於等候者和背景工作角色,省略位址會傾印目前的線程。 已定義下列旗標:0x1(單行輸出)、0x2(傾印成員)和0x4(傾印集區工作佇列)。

線程集區 API

使用線程集區函式