執行緒集區

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

執行緒集區架構

下列應用程式可以受益于使用執行緒集區:

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

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

執行緒集區架構包含下列各項:

  • 執行回呼函式的背景工作執行緒
  • 等候多個等候控制碼的等候程式執行緒
  • 工作佇列
  • 每個進程的預設執行緒集區
  • 管理背景工作執行緒的背景工作處理站

最佳做法

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

以下是使用執行緒集區時的最佳做法:

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

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

  • 先清除回呼函式中建立的所有資源,再從函式傳回。 其中包括 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

使用執行緒集區函式