共用方式為


工作佇列和線程改善

本主題描述 Windows 8 中的工作佇列和線程Microsoft媒體基礎平臺的改善。

Windows 7 行為

本節摘要說明 Windows 7 中 Media Foundation 工作佇列的行為。

工作佇列

Media Foundation 平臺會建立數個標準工作佇列。 只有兩個記錄為一般應用程式使用:

  • MFASYNC_CALLBACK_QUEUE_STANDARD
  • MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION

應用程式或元件可以呼叫 MFAllocateWorkQueueMFAllocateWorkQueueEx來配置新的工作佇列。 MFAllocateWorkQueueEx 函式會定義兩種類型的工作佇列:

  • MF_STANDARD_WORKQUEUE 建立沒有訊息迴圈的工作佇列。
  • MF_WINDOW_WORKQUEUE 使用訊息迴圈建立工作佇列。

若要將工作專案排入佇列,請呼叫 MFPutWorkItemMFPutWorkItemEx。 平臺會叫用由呼叫端提供實作 IMFAsyncCallback來執行工作專案。 在 Windows 7 和更早版本中,平臺會為每個工作佇列建立一個線程。

MMCSS 支援

多媒體類別排程器服務 (MMCSS) 會管理線程優先順序,讓多媒體應用程式取得 CPU 時間的一般配量,而不會拒絕 CPU 資源到較低優先順序的應用程式。 MMCSS 會定義一組具有不同 CPU 使用率設定檔的 工作。 當線程聯結 MMCSS 工作時,MMCSS 會根據數個因素來設定線程的優先順序:

  • 在登錄中設定之工作的基底優先順序。
  • 在執行時間設定的相對線程優先順序,方法是呼叫 AvSetMmThreadPriority
  • 各種運行時間特性,例如應用程式是否在前景,以及每個 MMCSS 類別中的線程會耗用多少 CPU 時間。

應用程式可以呼叫 MFBeginRegisterWorkQueueWithMMCSS,向 MMCSS 註冊工作佇列。 此函式會採用工作佇列標識碼、MMCSS 類別(工作名稱),以及 MMCSS 工作識別碼。 在內部,它會使用工作名稱和工作標識符呼叫 AvSetMmThreadCharacteristics。 使用 MMCSS 註冊工作佇列之後,您可以呼叫 MFGetWorkQueueMMCSSClassMFGetWorkQueueMMCSSTaskId來取得類別和工作識別符。

媒體會話 透過 IMFWorkQueueServices 介面,提供更上層的 API 存取權。 這個介面提供兩個主要方法:

方法 描述
BeginRegisterPlatformWorkQueueWithMMCSS 向 MMCSS 工作註冊工作佇列。 此方法基本上是 MFBeginRegisterWorkQueueWithMMCSS的精簡包裝函式,但您可以傳遞值 MFASYNC_CALLBACK_QUEUE_ALL 一次註冊所有平臺工作佇列。
BeginRegisterTopologyWorkQueuesWithMMCSS 向工作佇列註冊拓撲的分支。

 

若要註冊拓撲分支,請執行下列動作。

  1. 在分支的來源節點上設定 MF_TOPONODE_WORKQUEUE_ID 屬性。 使用任何應用程式定義的值。
  2. 或者,將 MF_TOPONODE_WORKQUEUE_MMCSS_CLASS 設定為將工作佇列加入 MMCSS 工作。
  3. 在解析的拓撲上呼叫 BeginRegisterTopologyWorkQueuesWithMMCSS

媒體工作會為每個唯一值設定新的工作佇列,MF_TOPONODE_WORKQUEUE_ID。 針對每個拓撲分支,異步管線作業會在指派給分支的工作佇列上執行。

IMFRealTimeClient

IMFRealTimeClient 介面適用於建立自己的線程或使用工作佇列進行異步作的管線元件。 媒體會話會使用此介面來通知管線元件正確的行為,如下所示:

一般而言,管線元件會使用線程或工作佇列來執行異步工作,但不是兩者。

Windows 8 改善

多線程工作佇列

在 Windows 8 中,Media Foundation 支援稱為 多線程佇列的新工作佇列類型。 多線程佇列會使用系統線程集區來分派工作專案。 多線程佇列會比先前的單個線程佇列更大規模。 例如

  • 數個元件可以共用多線程佇列,而不會彼此封鎖,因此需要建立較少的線程。

  • 工作專案已優化,以避免事件已設定時的內容切換。 這比建立自己的線程來等候事件更有效率。

IMFRealTimeClientEx時,應用程式應該避免啟動線程,而應該改用工作佇列。 若要達成此目的,應用程式應該實作 SetWorkQueueEx,而不要使用 RegisterThreadsUnregisterThreads

初始化 Media Foundation 平臺時,它會建立具有標識碼 MFASYNC_CALLBACK_QUEUE_MULTITHREADED的多線程佇列。

多線程佇列不會串行化工作專案。 每當線程集區中的線程可供使用時,就會分派佇列上的下一個工作專案。 呼叫端必須確保工作已正確串行化。 為了讓這更容易,Media Foundation 會定義 序列工作佇列。 序列佇列會包裝另一個工作佇列,但保證完全串行化執行。 在上一個專案完成之前,佇列上的下一個專案不會分派。

下列程式代碼會透過平臺多線程佇列建立串行化程式佇列。

DWORD workQueueID;
hr = MFAllocateSerialWorkQueue(MFASYNC_CALLBACK_QUEUE_MULTITHREADED, &workQueueID); 

多個序列佇列可以包裝相同的多線程佇列。 然後,序列佇列會共用相同的線程集區,並在每個佇列內強制執行串行化執行。

Windows 8 之前存在的標準工作佇列現在會實作為包裝平臺多線程佇列的序列工作佇列。 這項變更會保留回溯相容性。

共用工作工作佇列

若要正確使用核心排程器,您應該針對您使用的每個 MMCSS 工作,有一個多線程工作佇列。 媒體基礎平台會視需要配置這些專案,每個 MMCSS 工作每個進程最多一個。 若要取得特定 MMCSS 工作的共用工作佇列,請呼叫 MFLockSharedWorkQueue 並指定工作名稱。 函式會在數據表中查閱工作名稱。 如果此工作的工作佇列尚未存在,函式會配置新的 MT 工作佇列,並立即將它加入 MMCSS 工作。 如果工作的工作佇列已經存在,函式會傳回現有工作佇列的標識碼。

等候佇列

等候佇列 是一個特殊的平臺工作佇列,會等候事件發出訊號。 如果元件需要等候事件發出訊號,則可以使用等候佇列,而不是建立背景工作線程來等候事件。

若要使用等候佇列,請呼叫 MFPutWaitingWorkItem。 參數包括事件句柄和 IMFAsyncResult 指標。 當事件收到訊號時,等候佇列會叫用您的回呼。 有單一平臺等候佇列;應用程式無法建立自己的等候佇列。

MMCSS 支援的增強功能

下列新的媒體基礎平臺函式與 MMCSS 相關。

功能 描述
MFBeginRegisterWorkQueueWithMMCSSEx 向 MMCSS 註冊工作佇列。 此函式包含參數來指定相對線程優先順序。 在內部,這個值會轉譯成呼叫 AvSetMmThreadPriority
MFGetWorkQueueMMCSSPriority 查詢工作佇列的優先順序。
MFRegisterPlatformWithMMCSS 向 MMCSS 工作註冊所有平臺工作佇列。 此函式類似於 IMFWorkQueueServices::BeginRegisterPlatformWorkQueueWithMMCSS 方法,但不需要建立媒體會話的實例即可使用它。 此外,函式也包含參數來指定基底線程優先順序。

 

使用媒體會話的應用程式應該將音訊轉譯分支的 MF_TOPONODE_WORKQUEUE_MMCSS_CLASS 屬性設定為 “Audio”。 將影片轉譯分支的 屬性設定為 「播放」。

IMFRealTimeClientEx

IMFRealTimeClientEx 介面,以取代執行異步作之管線元件的 IMFRealTimeClient。

方法 描述
RegisterThreadsEx 通知元件向 MMCSS 註冊其線程。 這個方法相當於 IMFRealTimeClient::RegisterThreads,但它會新增基底線程優先權的參數。
SetWorkQueueEx 通知元件使用特定的工作佇列。 這個方法相當於 IMFReadTimeClient::SetWorkQueue,但它會新增工作專案優先順序的參數。
UnregisterThreads 通知元件從 MMCSS 取消註冊其線程。 此方法與 imfRealTimeClient::UnregisterThreads方法相同。

 

管線元件應該使用工作佇列,而且不應該建立背景工作線程,原因如下:

  • 工作佇列會變得更好,因為它們使用OS線程集區。
  • 平台會處理向 MMCSS 註冊工作佇列的詳細數據。
  • 背景工作線程很容易造成難以偵錯的死結。

此外,如果您需要串行化異步作,請考慮使用串行化程式工作佇列。

拓撲分支

如果 MF_TOPONODE_WORKQUEUE_MMCSS_CLASS 屬性向 MMCSS 註冊拓撲分支,在 Windows 8 中,媒體會話會使用共用 MT 工作佇列。 在舊版 Windows 中,媒體會話配置了新的工作佇列。

已定義兩個新的屬性,以向 MMCSS 註冊拓撲分支。

屬性 描述
MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY 指定基底線程優先順序。
MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY 指定工作項目優先順序。

 

建議

  • 使用媒體會話的應用程式應該將音訊轉譯分支的 MF_TOPONODE_WORKQUEUE_MMCSS_CLASS 設定為 「音訊」,而視訊轉譯分支的「播放」。
  • 使用媒體會話的應用程式應該在拓撲上呼叫 IMFWorkQueueServices::BeginRegisterTopologyWorkQueuesWithMMCSS
  • 針對管線元件,建議使用工作佇列,而不是背景工作線程。 如果元件使用工作佇列或背景工作線程,請實作 IMFRealTimeClientEx
  • 請勿建立私人工作佇列,因為這會失敗平臺工作佇列的目的。 使用平臺多線程佇列或包裝平臺多線程佇列的序列佇列。
  • 如果您需要串行化異步作,請使用序列佇列。

總結

下列與線程和工作佇列相關的媒體基礎平臺 API 是 Windows 8 的新功能。

工作佇列