Verwenden von Arbeitswarteschlangen

In diesem Thema wird beschrieben, wie Sie Arbeitswarteschlangen in Microsoft Media Foundation verwenden.

Verwenden von Arbeitswarteschlangen

Eine Arbeitswarteschlange ist eine effiziente Möglichkeit, asynchrone Vorgänge für einen anderen Thread auszuführen. Konzeptionell legen Sie Arbeitselemente in die Warteschlange, und die Warteschlange verfügt über einen Thread, der jedes Element aus der Warteschlange pullt und verteilt. Arbeitselemente werden mithilfe der IMFAsyncCallback-Schnittstelle als Rückrufe implementiert.

Media Foundation erstellt mehrere Standardarbeitswarteschlangen, die als Plattformarbeitswarteschlangen bezeichnet werden. Anwendungen können auch eigene Arbeitswarteschlangen erstellen, die als private Arbeitswarteschlangen bezeichnet werden. Eine Liste der Arbeitswarteschlangen der Plattform finden Sie unter Arbeitswarteschlangenbezeichner. Um eine private Arbeitswarteschlange zu erstellen, rufen Sie MFAllocateWorkQueue auf. Diese Funktion gibt einen Bezeichner für die neue Arbeitswarteschlange zurück. Um ein Element in der Warteschlange zu platzieren, rufen Sie MFPutWorkItem oder MFPutWorkItemEx auf. In beiden Fällen müssen Sie eine Rückrufschnittstelle angeben.

In beiden Fällen ruft der Arbeitswarteschlangenthread Ihre IMFAsyncCallback::Invoke-Methode auf. Verwenden Sie die Invoke-Methode , um das Arbeitselement auszuführen.

Wenn mehrere Threads oder Komponenten dieselbe Arbeitswarteschlange verwenden, können Sie MFLockWorkQueue aufrufen, um die Arbeitswarteschlange zu sperren, wodurch verhindert wird, dass die Plattform sie freigibt. Für jeden Aufruf von MFAllocateWorkQueue oder MFLockWorkQueue müssen Sie MFUnlockWorkQueue einmal aufrufen, um die Arbeitswarteschlange zu lösen. Wenn Sie beispielsweise eine neue Arbeitswarteschlange erstellen und diese einmal sperren, müssen Sie MFUnlockWorkQueue zweimal aufrufen, einmal für den Aufruf von MFAllocateWorkQueue und einmal für den Aufruf von MFLockWorkQueue.

Der folgende Code zeigt, wie Sie eine neue Arbeitswarteschlange erstellen, ein Arbeitselement in die Warteschlange einfügen und die Arbeitswarteschlange freigeben.

Weitere Informationen zu Arbeitswarteschlangen in Windows 8 finden Sie unter Verbesserungen bei Arbeitswarteschlangen und Threading.

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);
}

In diesem Beispiel wird davon ausgegangen, dass pCallback ein Zeiger auf die IMFAsyncCallback-Schnittstelle der Anwendung ist. Außerdem wird davon ausgegangen, dass der Rückruf das hEvent-Ereignishandle festlegt. Der Code wartet auf das Festlegen dieses Ereignisses, bevor MFUnlockWorkQueue aufgerufen wird.

Arbeitswarteschlangenthreads werden immer im Prozess des Aufrufers erstellt. Innerhalb jeder Arbeitswarteschlange werden die Rückrufe serialisiert. Wenn Sie MFPutWorkItem zweimal mit derselben Arbeitswarteschlange aufrufen, wird der zweite Rückruf erst aufgerufen, wenn der erste Rückruf zurückgegeben wurde.

Herunterfahren von Arbeitswarteschlangen

Geben Sie vor dem Aufrufen von MFShutdown alle Ressourcen frei, die von Arbeitswarteschlangenthreads verwendet werden. Um diesen Prozess zu synchronisieren, können Sie die Media Foundation-Plattform sperren, wodurch verhindert wird, dass die MFShutdown-Funktion alle Arbeitswarteschlangenthreads schließt. Wenn MFShutdown aufgerufen wird, während die Plattform gesperrt ist, wartet MFShutdown einige hundert Millisekunden, bis die Plattform entsperrt wird. Wenn es innerhalb dieser Zeit nicht entsperrt wird, schließt MFShutdown die Arbeitswarteschlangenthreads.

Die Standardimplementierung von IMFAsyncResult sperrt die Media Foundation-Plattform automatisch, wenn das Ergebnisobjekt erstellt wird. Durch das Freigeben der Schnittstelle wird die Plattform entsperrt. Daher müssen Sie die Plattform fast nie direkt sperren. Wenn Sie jedoch Ihre eigene benutzerdefinierte Implementierung von IMFAsyncResult schreiben, sollten Sie die Plattform manuell sperren und entsperren. Um die Plattform zu sperren, rufen Sie MFLockPlatform auf. Um die Plattform zu entsperren, rufen Sie MFUnlockPlatform auf. Ein Beispiel finden Sie unter Benutzerdefinierte asynchrone Ergebnisobjekte.

Nachdem Sie MFShutdown aufgerufen haben, müssen Sie sicherstellen, dass die Plattform innerhalb des 5-Sekunden-Timeoutzeitraums entsperrt ist. Führen Sie hierzu alle IMFAsyncResult-Zeiger aus, und rufen Sie MFUnlockPlatform auf, wenn Sie die Plattform manuell gesperrt haben. Stellen Sie sicher, dass Sie alle Ressourcen freigeben, die von Arbeitswarteschlangenthreads verwendet werden, da ihre Anwendung möglicherweise Arbeitsspeicher verloren hat.

Wenn Ihre Anwendung jedes Media Foundation-Objekt vor dem Aufrufen von MFShutdown herunterfährt und freigibt, müssen Sie sich in der Regel keine Gedanken über das Sperren machen. Mit dem Sperrmechanismus können Arbeitswarteschlangenthreads einfach ordnungsgemäß beendet werden, nachdem Sie MFShutdown aufgerufen haben.

Verwenden geplanter Arbeitselemente

Sie können einen Rückruf nach einem bestimmten Zeitraum planen, indem Sie MFScheduleWorkItem oder MFScheduleWorkItemEx aufrufen.

  • MFScheduleWorkItem verwendet einen Zeiger auf Ihren Rückruf, ein optionales Zustandsobjekt und ein Timeoutintervall.
  • MFScheduleWorkItemEx verwendet einen Zeiger auf ein asynchrones Ergebnisobjekt und einen Timeoutwert.

Geben Sie das Timeout als negativen Wert in Millisekunden an. Verwenden Sie beispielsweise den Wert −5000, um den Aufruf eines Rückrufs in 5 Sekunden zu planen. Beide Funktionen geben einen MFWORKITEM_KEY Wert zurück, mit dem Sie den Rückruf abbrechen können, indem Sie ihn an die MFCancelWorkItem-Funktion übergeben.

Geplante Arbeitselemente verwenden immer die Arbeitswarteschlange MFASYNC_CALLBACK_QUEUE_TIMER Plattform.

Verwenden regelmäßiger Rückrufe

Die MFAddPeriodicCallback-Funktion plant, dass ein Rückruf regelmäßig aufgerufen wird, bis Sie ihn abbrechen. Das Rückrufintervall ist festgelegt. anwendungen können sie nicht ändern. Um das genaue Intervall zu ermitteln, rufen Sie MFGetTimerPeriodicity auf. Das Intervall liegt bei 10 Millisekunden, sodass diese Funktion für Situationen bestimmt ist, in denen Sie häufig ein "Tick" benötigen, z. B. die Implementierung einer Präsentationsuhr. Wenn Sie einen Vorgang so planen möchten, dass er weniger häufig auftritt, verwenden Sie ein geplantes Arbeitselement, wie zuvor beschrieben.

Im Gegensatz zu den anderen in diesem Thema beschriebenen Rückrufen verwendet der regelmäßige Rückruf nicht die IMFAsyncCallback-Schnittstelle . Stattdessen wird ein Funktionszeiger verwendet. Weitere Informationen finden Sie unter MFPERIODICCALLBACK Rückruf.

Um den regelmäßigen Rückruf abzubrechen, rufen Sie MFRemovePeriodicCallback auf.

Regelmäßige Rückrufe verwenden die MFASYNC_CALLBACK_QUEUE_TIMER Arbeitswarteschlange der Plattform.

Arbeitswarteschlangen

MFASYNCRESULT

Verbesserungen bei Arbeitswarteschlange und Threading