Share via


使用工作佇列

本主題描述如何在 Microsoft Media Foundation 中使用工作佇列。

使用工作佇列

工作佇列是在另一個執行緒上執行非同步作業的有效方式。 就概念上,您會將工作專案放在佇列中,而佇列有一個執行緒可從佇列提取每個專案並分派它。 工作專案會使用 IMFAsyncCallback 介面實作為回呼。

Media Foundation 會建立數個標準工作佇列,稱為 平臺工作佇列。 應用程式也可以建立自己的工作佇列,稱為 私人工作佇列。 如需平臺工作佇列的清單,請參閱 工作佇列識別碼。 若要建立私人工作佇列,請呼叫 MFAllocateWorkQueue。 此函式會傳回新工作佇列的識別碼。 若要將專案放在佇列中,請呼叫 MFPutWorkItemMFPutWorkItemEx。 在這兩種情況下,您必須指定回呼介面。

在這兩種情況下,工作佇列執行緒都會呼叫 您的 IMFAsyncCallback::Invoke 方法。 使用 Invoke 方法來執行工作專案。

如果多個執行緒或元件共用相同的工作佇列,您可以呼叫 MFLockWorkQueue 來鎖定工作佇列,以防止平臺釋放工作佇列。 對於 MFAllocateWorkQueueMFLockWorkQueue的每個呼叫,您必須呼叫 MFUnlockWorkQueue 一次,才能釋放工作佇列。 例如,如果您建立新的工作佇列,然後將它鎖定一次,則必須呼叫 MFUnlockWorkQueue 兩次,一次呼叫 MFAllocateWorkQueue ,一次用於 MFLockWorkQueue呼叫。

下列程式碼示範如何建立新的工作佇列、將工作專案放在佇列中,以及釋放工作佇列。

如需Windows 8中工作佇列的其他資訊,請參閱工作佇列和執行緒改善

DWORD idWorkQueue = 0;
HRESULT hr = S_OK;

// Create a new work queue.
hr = MFAllocateWorkQueue(&idWorkQueue);

// Put an item on the queue.
if (SUCCEEDED(hr))
{
    hr = MFPutWorkItem(idWorkQueue, pCallback, NULL);
}

// Wait for the callback to be invoked.
if (SUCCEEDED(hr))
{
    WaitForSingleObject(hEvent, INFINITE);
}

// Release the work queue.
if (SUCCEEDED(hr))
{
    hr = MFUnlockWorkQueue(idWorkQueue);
}

此範例假設 pCallback 是應用程式 IMFAsyncCallback 介面的指標。 它也假設回呼會設定 hEvent 事件控制碼。 程式碼會等候設定此事件,再呼叫 MFUnlockWorkQueue

工作佇列執行緒一律會在呼叫端的進程中建立。 在每個工作佇列中,回呼都會序列化。 如果您使用相同的工作佇列呼叫 MFPutWorkItem 兩次,則在第一個回呼傳回之前,不會叫用第二個回呼。

關閉工作佇列

在呼叫 MFShutdown之前,請釋放工作佇列執行緒正在使用的任何資源。 若要同步處理此程式,您可以鎖定 Media Foundation 平臺,以防止 MFShutdown 函式關閉任何工作佇列執行緒。 如果在平臺鎖定時呼叫 MFShutdownMFShutdown 會等候數百毫秒才能解除鎖定平臺。 如果未在該時間內解除鎖定, MFShutdown 會關閉工作佇列執行緒。

建立結果物件時, IMFAsyncResult 的預設實作會自動鎖定媒體基礎平臺。 釋放介面會解除鎖定平臺。 因此,您幾乎不需要直接鎖定平臺。 但是,如果您撰寫自己的 IMFAsyncResult自訂實作,則應該手動鎖定和解除鎖定平臺。 若要鎖定平臺,請呼叫 MFLockPlatform。 若要解除鎖定平臺,請呼叫 MFUnlockPlatform。 如需範例,請參閱 自訂非同步結果物件

呼叫 MFShutdown之後,您必須確保平臺在 5 秒逾時期間內解除鎖定。 請釋放所有 IMFAsyncResult 指標,並在手動鎖定平臺時呼叫 MFUnlockPlatform 來執行 此動作。 請務必釋放工作佇列執行緒正在使用的任何資源,或您的應用程式可能會流失記憶體。

一般而言,如果您的應用程式在呼叫 MFShutdown之前關閉並釋放每個 Media Foundation 物件,您就不需要擔心鎖定。 鎖定機制只會讓工作佇列執行緒在您呼叫 MFShutdown之後正常結束。

使用排程的工作專案

您可以藉由呼叫 MFScheduleWorkItemMFScheduleWorkItemEx,將回呼排程在一段時間後發生。

以毫秒為單位,將逾時指定為負值。 例如,若要排程在 5 秒內叫用的回呼,請使用值 -5000。 這兩個函式都會傳回 MFWORKITEM_KEY 值,您可以將其傳遞至 MFCancelWorkItem 函式,以用來取消回呼。

排程的工作專案一律使用MFASYNC_CALLBACK_QUEUE_TIMER平臺工作佇列。

使用定期回呼

MFAddPeriodicCallback函式會排程要定期叫用的回呼,直到取消為止。 回呼間隔是固定的;應用程式無法變更它。 若要找出確切的間隔,請呼叫 MFGetTimerPeriodicity。 間隔的順序為 10 毫秒,因此此函式適用于您需要頻繁「刻度」的情況,例如實作簡報時鐘。 如果您想要排程作業較不頻繁發生,請使用排程的工作專案,如先前所述。

不同于本主題所述的其他回呼,定期回呼不會使用 IMFAsyncCallback 介面。 相反地,它會使用函式指標。 如需詳細資訊,請參閱 MFPERIODICCALLBACK 回呼

若要取消定期回呼,請呼叫 MFRemovePeriodicCallback

定期回呼會使用MFASYNC_CALLBACK_QUEUE_TIMER平臺工作佇列。

工作佇列

MFASYNCRESULT

工作佇列和執行緒改善