工作佇列和執行緒改善

本主題描述 Microsoft Media Foundation 平臺中工作佇列和執行緒Windows 8改善。

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 支援的增強功能

下列新的 Media Foundation 平臺函式與 MMCSS 相關。

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

 

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

IMFRealTimeClientEx

針對執行非同步作業的管線元件,用來取代 IMFRealTimeClient 的 IMFRealTimeClientEx 介面。

方法 描述
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的新功能。

工作佇列