Verbesserungen bei Arbeitswarteschlange und Threading

In diesem Thema werden Verbesserungen bei Windows 8 für Arbeitswarteschlangen und Threading auf der Microsoft Media Foundation-Plattform beschrieben.

Windows 7-Verhalten

In diesem Abschnitt wird das Verhalten von Media Foundation-Arbeitswarteschlangen in Windows 7 zusammengefasst.

Arbeitswarteschlangen

Die Media Foundation-Plattform erstellt mehrere Standardarbeitswarteschlangen. Nur zwei sind für die allgemeine Anwendungsverwendung dokumentiert:

  • MFASYNC_CALLBACK_QUEUE_STANDARD
  • MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION

Eine Anwendung oder Komponente kann neue Arbeitswarteschlangen zuordnen, indem sie MFAllocateWorkQueue oder MFAllocateWorkQueueEx aufruft. Die MFAllocateWorkQueueEx-Funktion definiert zwei Arten von Arbeitswarteschlangen:

  • MF_STANDARD_WORKQUEUE erstellt eine Arbeitswarteschlange ohne Nachrichtenschleife.
  • MF_WINDOW_WORKQUEUE erstellt eine Arbeitswarteschlange mit einer Nachrichtenschleife.

Um ein Arbeitselement in die Warteschlange zu stellen, rufen Sie MFPutWorkItem oderMFPutWorkItemEx auf. Die Plattform führt das Arbeitselement aus, indem die vom Aufrufer bereitgestellte Implementierung von IMFAsyncCallback aufgerufen wird. In Windows 7 und früher erstellt die Plattform einen Thread pro Arbeitswarteschlange.

MMCSS-Unterstützung

Der Multimedia Class Scheduler Service (MMCSS) verwaltet Threadprioritäten, sodass Multimediaanwendungen regelmäßige Slices der CPU-Zeit erhalten, ohne CPU-Ressourcen Anwendungen mit niedrigerer Priorität zu verweigern. MMCSS definiert eine Reihe von Aufgaben mit unterschiedlichen CPU-Auslastungsprofilen. Wenn ein Thread eine MMCSS-Aufgabe verknüpft, legt MMCSS die Priorität des Threads basierend auf mehreren Faktoren fest:

  • Die Basispriorität der Aufgabe, die in der Registrierung festgelegt wird.
  • Die relative Threadpriorität, die zur Laufzeit durch Aufrufen von AvSetMmThreadPriority festgelegt wird.
  • Verschiedene Laufzeitmerkmale, z. B. ob sich die Anwendung im Vordergrund befindet und wie viel CPU-Zeit von den Threads in jeder MMCSS-Klasse verbraucht wird.

Eine Anwendung kann eine Arbeitswarteschlange bei MMCSS registrieren, indem sie MFBeginRegisterWorkQueueWithMMCSS aufruft. Diese Funktion übernimmt eine Arbeitswarteschlangen-ID, eine MMCSS-Klasse (Aufgabenname) und den MMCSS-Aufgabenbezeichner. Intern wird AvSetMmThreadCharacteristics mit dem Aufgabennamen und der Aufgaben-ID aufgerufen. Nachdem eine Arbeitswarteschlange bei MMCSS registriert wurde, können Sie die Klassen- und Aufgaben-ID abrufen, indem Sie MFGetWorkQueueMMCSSClass und MFGetWorkQueueMMCSSTaskId aufrufen.

Die Mediensitzung bietet über die IMFWorkQueueServices-Schnittstelle zugriff auf diese APIs auf etwas höherer Ebene. Diese Schnittstelle bietet zwei primäre Methoden:

Methode BESCHREIBUNG
BeginRegisterPlatformWorkQueueWithMMCSS Registriert eine Arbeitswarteschlange bei einem MMCSS-Task. Diese Methode ist im Wesentlichen ein dünner Wrapper um MFBeginRegisterWorkQueueWithMMCSS, aber Sie können den Wert MFASYNC_CALLBACK_QUEUE_ALL übergeben, um alle Arbeitswarteschlangen der Plattform gleichzeitig zu registrieren.
BeginRegisterTopologyWorkQueuesWithMMCSS Registriert einen Branch der Topologie bei einer Arbeitswarteschlange.

 

Gehen Sie wie folgt vor, um einen Topologiebranch zu registrieren.

  1. Legen Sie das attribut MF_TOPONODE_WORKQUEUE_ID auf dem Quellknoten für den Branch fest. Verwenden Sie einen beliebigen anwendungsdefinierten Wert.
  2. Legen Sie optional die MF_TOPONODE_WORKQUEUE_MMCSS_CLASS fest, um die Arbeitswarteschlange mit einer MMCSS-Aufgabe zu verknüpfen.
  3. Rufen Sie BeginRegisterTopologyWorkQueuesWithMMCSS für die aufgelöste Topologie auf.

Die Mediensitzung weist jedem eindeutigen Wert von MF_TOPONODE_WORKQUEUE_ID eine neue Arbeitswarteschlange zu. Für jeden Topologiebranch werden asynchrone Pipelinevorgänge für die Arbeitswarteschlange ausgeführt, die dem Branch zugewiesen ist.

IMFRealTimeClient

Die IMFRealTimeClient-Schnittstelle ist für Pipelinekomponenten vorgesehen, die entweder eigene Threads erstellen oder Arbeitswarteschlangen für asynchrone Vorgänge verwenden. Die Mediensitzung verwendet diese Schnittstelle, um die Pipelinekomponente wie folgt über das richtige Verhalten zu benachrichtigen:

In der Regel verwendet eine Pipelinekomponente entweder einen Thread oder eine Arbeitswarteschlange, um asynchrone Aufgaben auszuführen, aber nicht beides.

Windows 8 Verbesserungen

Multithreadarbeitswarteschlangen

In Windows 8 unterstützt Media Foundation eine neue Art von Arbeitswarteschlange namens Multithreadwarteschlange. Eine Multithreadwarteschlange verwendet einen Systemthreadpool, um Arbeitselemente zu senden. Die Multithreadwarteschlange skaliert besser als die vorherigen Singlethread-Warteschlangen. Beispiel:

  • Mehrere Komponenten können eine Multithreadwarteschlange gemeinsam nutzen, ohne sich gegenseitig zu blockieren, sodass weniger Threads erstellt werden müssen.

  • Arbeitselemente sind optimiert, um Kontextwechsel zu vermeiden, wenn bereits ein Ereignis festgelegt ist. Dies ist effizienter als das Erstellen eigener Threads zum Warten auf Ereignisse.

Bei Verwendung von IMFRealTimeClientEx sollten Anwendungen das Hochfahren von Threads vermeiden und stattdessen die Arbeitswarteschlangen verwenden. Hierzu sollten Anwendungen SetWorkQueueEx implementieren und nicht RegisterThreads und UnregisterThreads verwenden.

Wenn die Media Foundation-Plattform initialisiert wird, wird eine Multithreadwarteschlange mit dem Bezeichner MFASYNC_CALLBACK_QUEUE_MULTITHREADED erstellt.

Eine Multithreadwarteschlange serialisiert keine Arbeitselemente. Wenn ein Thread aus dem Threadpool verfügbar wird, wird das nächste Arbeitselement in der Warteschlange verteilt. Der Aufrufer muss sicherstellen, dass die Arbeit ordnungsgemäß serialisiert wird. Um dies zu vereinfachen, definiert Media Foundation eine serielle Arbeitswarteschlange. Eine serielle Warteschlange umschließt eine andere Arbeitswarteschlange, garantiert jedoch eine vollständig serialisierte Ausführung. Das nächste Element in der Warteschlange wird erst dann versendet, wenn das vorherige Element abgeschlossen ist.

Der folgende Code erstellt eine Serialisierungswarteschlange über der Plattform-Multithreadwarteschlange.

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

Mehrere serielle Warteschlange können dieselbe Multithreadwarteschlange umschließen. Die seriellen Warteschlangen verwenden dann denselben Threadpool, und die serialisierte Ausführung wird in jeder Warteschlange erzwungen.

Die Standardarbeitswarteschlangen, die vor Windows 8 vorhanden waren, werden jetzt als serielle Arbeitswarteschlangen implementiert, die die Plattform-Multithreadwarteschlange umschließen. Diese Änderung behält die Abwärtskompatibilität bei.

Arbeitswarteschlangen für freigegebene Aufgaben

Damit sie ordnungsgemäß mit dem Kernelplaner arbeiten können, sollte für jede von Ihnen verwendete MMCSS-Aufgabe eine Multithreadarbeitswarteschlange vorhanden sein. Die Media Foundation-Plattform weist diese nach Bedarf zu, bis zu einem Vorgang pro MMCSS-Aufgabe. Um die freigegebene Arbeitswarteschlange für eine bestimmte MMCSS-Aufgabe abzurufen, rufen Sie MFLockSharedWorkQueue auf , und geben Sie den Vorgangsnamen an. Die Funktion sucht den Aufgabennamen in einer Tabelle. Wenn für diese Aufgabe noch keine Arbeitswarteschlange vorhanden ist, weist die Funktion eine neue MT-Arbeitswarteschlange zu und fügt sie sofort dem MMCSS-Task zu. Wenn für diese Aufgabe bereits eine Arbeitswarteschlange vorhanden ist, gibt die Funktion den Bezeichner der vorhandenen Arbeitswarteschlange zurück.

Warteschleife

Die Warteschleife ist eine spezielle Plattformarbeitswarteschlange, die auf Ereignisse wartet, die signalisiert werden sollen. Wenn eine Komponente warten muss, bis ein Ereignis signalisiert wird, kann sie die Warteschleife verwenden, anstatt einen Workerthread zu erstellen, um auf das Ereignis zu warten.

Um die Warteschleife zu verwenden, rufen Sie MFPutWaitingWorkItem auf. Die Parameter umfassen das Ereignishandle und einen IMFAsyncResult-Zeiger . Wenn das Ereignis signalisiert wird, ruft die Wartewarteschlange Ihren Rückruf auf. Es gibt eine einzelne Plattformwartewarteschlange. Anwendungen können keine eigenen Warteschleifen erstellen.

Verbesserungen an der MMCSS-Unterstützung

Die folgenden neuen Media Foundation-Plattformfunktionen beziehen sich auf MMCSS.

Funktion BESCHREIBUNG
MFBeginRegisterWorkQueueWithMMCSSEx Registriert eine Arbeitswarteschlange bei MMCSS. Diese Funktion enthält einen Parameter zum Angeben der relativen Threadpriorität. Intern wird dieser Wert in einen Aufruf von AvSetMmThreadPriority übersetzt.
MFGetWorkQueueMMCSSPriority Fragt die Priorität einer Arbeitswarteschlange ab.
MFRegisterPlatformWithMMCSS Registriert alle Arbeitswarteschlangen der Plattform mit einem MMCSS-Task. Diese Funktion ähnelt der IMFWorkQueueServices::BeginRegisterPlatformWorkQueueWithMMCSS-Methode, kann jedoch verwendet werden, ohne eine instance der Mediensitzung zu erstellen. Darüber hinaus enthält die Funktion einen Parameter, um die Basisthreadpriorität anzugeben.

 

Anwendungen, die die Mediensitzung verwenden, sollten das MF_TOPONODE_WORKQUEUE_MMCSS_CLASS-Attribut für den Audiorendering-Branch auf "Audio" festlegen. Legen Sie das Attribut für den Videorendering-Branch auf "Playback" fest.

IMFRealTimeClientEx

Die IMFRealTimeClientEx-Schnittstelle zum Ersetzen von IMFRealTimeClient für Pipelinekomponenten, die asynchrone Vorgänge ausführen.

Methode BESCHREIBUNG
RegisterThreadsEx Benachrichtigt die Komponente, ihre Threads bei MMCSS zu registrieren. Diese Methode entspricht IMFRealTimeClient::RegisterThreads, fügt jedoch einen Parameter für die Basisthreadpriorität hinzu.
SetWorkQueueEx Benachrichtigt die Komponente, eine bestimmte Arbeitswarteschlange zu verwenden. Diese Methode entspricht IMFReadTimeClient::SetWorkQueue, fügt jedoch einen Parameter für die Arbeitselementpriorität hinzu.
Aufheben der RegistrierungThreads Benachrichtigt die Komponente, die Registrierung ihrer Threads aus MMCSS aufzuheben. Diese Methode ist identisch mit der IMFRealTimeClient::UnregisterThreads-Methode .

 

Pipelinekomponenten sollten Arbeitswarteschlangen verwenden und aus den folgenden Gründen keine Workerthreads erstellen:

  • Arbeitswarteschlangen werden besser skaliert, da sie die Betriebssystemthreadpools verwenden.
  • Die Plattform verarbeitet die Details zum Registrieren von Arbeitswarteschlangen bei MMCSS.
  • Ein Workerthread kann leicht einen Deadlock verursachen, der schwer zu debuggen ist.

Erwägen Sie außerdem die Verwendung der Arbeitswarteschlange des Serialisierungsprogramms, wenn Sie Ihre asynchronen Vorgänge serialisieren müssen.

Topologie-Branches

Wenn das MF_TOPONODE_WORKQUEUE_MMCSS_CLASS-Attribut einen Topologiebranch bei MMCSS registriert, verwendet die Mediensitzung in Windows 8 die freigegebenen MT-Arbeitswarteschlangen. In früheren Versionen von Windows hat die Mediensitzung eine neue Arbeitswarteschlange zugewiesen.

Für die Registrierung eines Topologiebranchs bei MMCSS werden zwei neue Attribute definiert.

attribute BESCHREIBUNG
MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY Gibt die Basisthreadpriorität an.
MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY Gibt die Arbeitselementpriorität an.

 

Empfehlungen

  • Anwendungen, die die Mediensitzung verwenden, sollten MF_TOPONODE_WORKQUEUE_MMCSS_CLASS auf "Audio" für den Audiorendering-Branch und "Wiedergabe" für den Videorendering-Branch festlegen.
  • Anwendungen, die die Mediensitzung verwenden, sollten IMFWorkQueueServices::BeginRegisterTopologyWorkQueuesWithMMCSS für die Topologie aufrufen.
  • Für Pipelinekomponenten werden Arbeitswarteschlangen anstelle von Workerthreads empfohlen. Wenn die Komponente Arbeitswarteschlangen oder Workerthreads verwendet, implementieren Sie IMFRealTimeClientEx.
  • Erstellen Sie keine privaten Arbeitswarteschlangen, da dadurch der Zweck der Plattformarbeitswarteschlangen verfehlt wird. Verwenden Sie entweder die Plattform-Multithreadwarteschlange oder eine serielle Warteschlange, die die Plattform-Multithreadwarteschlange umschließt.
  • Wenn Sie asynchrone Vorgänge serialisieren müssen, verwenden Sie eine serielle Warteschlange.

Zusammenfassung

Die folgenden Media Foundation-Plattform-APIs, die sich auf Threads und Arbeitswarteschlangen beziehen, sind für Windows 8 neu.

Arbeitswarteschlangen