使用工作佇列
本主題描述如何在 Microsoft Media Foundation 中使用工作佇列。
使用工作佇列
工作佇列是在另一個執行緒上執行非同步作業的有效方式。 就概念上,您會將工作專案放在佇列中,而佇列有一個執行緒可從佇列提取每個專案並分派它。 工作專案會使用 IMFAsyncCallback 介面實作為回呼。
Media Foundation 會建立數個標準工作佇列,稱為 平臺工作佇列。 應用程式也可以建立自己的工作佇列,稱為 私人工作佇列。 如需平臺工作佇列的清單,請參閱 工作佇列識別碼。 若要建立私人工作佇列,請呼叫 MFAllocateWorkQueue。 此函式會傳回新工作佇列的識別碼。 若要將專案放在佇列中,請呼叫 MFPutWorkItem 或 MFPutWorkItemEx。 在這兩種情況下,您必須指定回呼介面。
- MFPutWorkItem 會取得 IMFAsyncCallback 介面的指標,加上實作 IUnknown的選擇性狀態物件。 這些是非同步方法中使用的相同參數,如 非同步回呼方法主題中所述。 在內部,此函式會建立異步結果物件,此物件會傳遞至回呼的 Invoke 方法。
- MFPutWorkItemEx 會取得 IMFAsyncResult 介面的指標。 這個介面代表非同步結果物件。 呼叫 MFCreateAsyncResult 並指定回呼介面,並選擇性地指定狀態物件,以建立此物件。
在這兩種情況下,工作佇列執行緒都會呼叫 您的 IMFAsyncCallback::Invoke 方法。 使用 Invoke 方法來執行工作專案。
如果多個執行緒或元件共用相同的工作佇列,您可以呼叫 MFLockWorkQueue 來鎖定工作佇列,以防止平臺釋放工作佇列。 對於 MFAllocateWorkQueue 或 MFLockWorkQueue的每個呼叫,您必須呼叫 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 函式關閉任何工作佇列執行緒。 如果在平臺鎖定時呼叫 MFShutdown , MFShutdown 會等候數百毫秒才能解除鎖定平臺。 如果未在該時間內解除鎖定, MFShutdown 會關閉工作佇列執行緒。
建立結果物件時, IMFAsyncResult 的預設實作會自動鎖定媒體基礎平臺。 釋放介面會解除鎖定平臺。 因此,您幾乎不需要直接鎖定平臺。 但是,如果您撰寫自己的 IMFAsyncResult自訂實作,則應該手動鎖定和解除鎖定平臺。 若要鎖定平臺,請呼叫 MFLockPlatform。 若要解除鎖定平臺,請呼叫 MFUnlockPlatform。 如需範例,請參閱 自訂非同步結果物件。
呼叫 MFShutdown之後,您必須確保平臺在 5 秒逾時期間內解除鎖定。 請釋放所有 IMFAsyncResult 指標,並在手動鎖定平臺時呼叫 MFUnlockPlatform 來執行 此動作。 請務必釋放工作佇列執行緒正在使用的任何資源,或您的應用程式可能會流失記憶體。
一般而言,如果您的應用程式在呼叫 MFShutdown之前關閉並釋放每個 Media Foundation 物件,您就不需要擔心鎖定。 鎖定機制只會讓工作佇列執行緒在您呼叫 MFShutdown之後正常結束。
使用排程的工作專案
您可以藉由呼叫 MFScheduleWorkItem 或 MFScheduleWorkItemEx,將回呼排程在一段時間後發生。
- MFScheduleWorkItem 會取得回呼的指標、選擇性狀態物件,以及逾時間隔。
- MFScheduleWorkItemEx 會採用非同步結果物件的指標和逾時值。
以毫秒為單位,將逾時指定為負值。 例如,若要排程在 5 秒內叫用的回呼,請使用值 -5000。 這兩個函式都會傳回 MFWORKITEM_KEY 值,您可以將其傳遞至 MFCancelWorkItem 函式,以用來取消回呼。
排程的工作專案一律使用MFASYNC_CALLBACK_QUEUE_TIMER平臺工作佇列。
使用定期回呼
MFAddPeriodicCallback函式會排程要定期叫用的回呼,直到取消為止。 回呼間隔是固定的;應用程式無法變更它。 若要找出確切的間隔,請呼叫 MFGetTimerPeriodicity。 間隔的順序為 10 毫秒,因此此函式適用于您需要頻繁「刻度」的情況,例如實作簡報時鐘。 如果您想要排程作業較不頻繁發生,請使用排程的工作專案,如先前所述。
不同于本主題所述的其他回呼,定期回呼不會使用 IMFAsyncCallback 介面。 相反地,它會使用函式指標。 如需詳細資訊,請參閱 MFPERIODICCALLBACK 回呼。
若要取消定期回呼,請呼叫 MFRemovePeriodicCallback。
定期回呼會使用MFASYNC_CALLBACK_QUEUE_TIMER平臺工作佇列。
相關主題