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.
- Legen Sie das attribut MF_TOPONODE_WORKQUEUE_ID auf dem Quellknoten für den Branch fest. Verwenden Sie einen beliebigen anwendungsdefinierten Wert.
- Legen Sie optional die MF_TOPONODE_WORKQUEUE_MMCSS_CLASS fest, um die Arbeitswarteschlange mit einer MMCSS-Aufgabe zu verknüpfen.
- 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:
- Wenn die Pipelinekomponente einen Workerthread erstellt, benachrichtigt die IMFRealTimeClient::RegisterThreads-Methode die Komponente, welche MMCSS-Klasse verknüpft werden soll.
- Wenn die Pipelinekomponente eine Arbeitswarteschlange verwendet, teilt die IMFRealTimeClient::SetWorkQueue-Methode der Komponente mit, welche Arbeitswarteschlange verwendet werden soll.
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.
- MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY
- MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY
- MFAllocateSerialWorkQueue
- MFBeginRegisterWorkQueueWithMMCSSEx
- MFGetWorkQueueMMCSSPriority
- MFPutWaitingWorkItem
- MFPutWorkItem2
- MFPutWorkItemEx2
- MFRegisterPlatformWithMMCSS
- MFUnregisterPlatformFromMMCSS
- MFLockSharedWorkQueue
- IMFRealTimeClientEx
Zugehörige Themen