Condividi tramite


Miglioramenti della coda di lavoro e del threading

Questo argomento descrive i miglioramenti delle Windows 8 per le code di lavoro e il threading nella piattaforma Microsoft Media Foundation.

Comportamento di Windows 7

Questa sezione riepiloga il comportamento delle code di lavoro di Media Foundation in Windows 7.

Code di lavoro

La piattaforma Media Foundation crea diverse code di lavoro standard. Solo due sono documentati come per l'uso generale dell'applicazione:

  • MFASYNC_CALLBACK_QUEUE_STANDARD
  • MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION

Un'applicazione o un componente può allocare nuove code di lavoro chiamando MFAllocateWorkQueue o MFAllocateWorkQueueEx. La funzione MFAllocateWorkQueueEx definisce due tipi di coda di lavoro:

  • MF_STANDARD_WORKQUEUE crea una coda di lavoro senza un ciclo di messaggi.
  • MF_WINDOW_WORKQUEUE crea una coda di lavoro con un ciclo di messaggi.

Per accodare un elemento di lavoro, chiamare MFPutWorkItem o MFPutWorkItemEx. La piattaforma esegue l'elemento di lavoro richiamando l'implementazione fornita dal chiamante di FMAsyncCallback. In Windows 7 e versioni precedenti la piattaforma crea un thread per coda di lavoro.

Supporto MMCSS

Il servizio utilità di pianificazione della classe multimediale (MMCSS) gestisce le priorità del thread in modo che le applicazioni multimediali ottengano una sezione regolare del tempo della CPU, senza negare le risorse DELLA CPU alle applicazioni con priorità inferiore. MMCSS definisce un set di attività con profili di utilizzo della CPU diversi. Quando un thread aggiunge un'attività MMCSS, MMCSS imposta la priorità del thread in base a diversi fattori:

  • Priorità di base dell'attività, impostata nel Registro di sistema.
  • Priorità relativa del thread, impostata in fase di esecuzione chiamando AvSetMmThreadPriority.
  • Varie caratteristiche di runtime, ad esempio se l'applicazione è in primo piano e la quantità di tempo di CPU utilizzata dai thread in ogni classe MMCSS.

Un'applicazione può registrare una coda di lavoro con MMCSS chiamando MFBeginRegisterWorkQueueWithMMCSS. Questa funzione accetta un ID coda di lavoro, una classe MMCSS (nome attività) e l'identificatore dell'attività MMCSS. Internamente, chiama AvSetMmThreadCharacteristics con il nome dell'attività e l'ID attività. Dopo aver registrato una coda di lavoro con MMCSS, è possibile ottenere l'ID della classe e dell'attività chiamando MFGetWorkQueueMMCSSClass e MFGetWorkQueueMMCSSTaskId.

La sessione multimediale offre un accesso di livello leggermente superiore a queste API tramite l'interfaccia FMWorkQueueServices . Questa interfaccia fornisce due metodi primari:

Metodo Descrizione
BeginRegisterPlatformWorkQueueWithMMCSS Registra una coda di lavoro con un'attività MMCSS. Questo metodo è essenzialmente un wrapper sottile intorno a MFBeginRegisterWorkQueueWithMMCSS, ma è possibile passare il valore MFASYNC_CALLBACK_QUEUE_ALL per registrare tutte le code di lavoro della piattaforma contemporaneamente.
BeginRegisterTopologyWorkQueuesWithMMCSS Registra un ramo della topologia con una coda di lavoro.

 

Per registrare un ramo di topologia, eseguire le operazioni seguenti.

  1. Impostare l'attributo MF_TOPONODE_WORKQUEUE_ID nel nodo di origine per il ramo. Usare qualsiasi valore definito dall'applicazione.
  2. Facoltativamente, impostare l'MF_TOPONODE_WORKQUEUE_MMCSS_CLASS per aggiungere la coda di lavoro a un'attività MMCSS.
  3. Chiamare BeginRegisterTopologyWorkQueuesWithMMCSS nella topologia risolta.

La sessione multimediale alloca una nuova coda di lavoro per ogni valore univoco di MF_TOPONODE_WORKQUEUE_ID. Per ogni ramo della topologia, le operazioni della pipeline asincrone vengono eseguite nella coda di lavoro assegnata al ramo.

FMRealTimeClient

L'interfaccia IMFRealTimeClient è destinata ai componenti della pipeline che creano i propri thread o usano code di lavoro per le operazioni asincrone. La sessione multimediale usa questa interfaccia per notificare al componente della pipeline il comportamento corretto, come indicato di seguito:

In genere, un componente della pipeline usa un thread o una coda di lavoro per eseguire attività asincrone, ma non entrambe.

miglioramenti Windows 8

Code di lavoro multithreaded

In Windows 8 Media Foundation supporta un nuovo tipo di coda di lavoro denominata coda multithreaded. Una coda multithreaded usa un pool di thread di sistema per inviare elementi di lavoro. Le code multithreaded ridimensionano meglio delle code a thread singolo precedenti. Ad esempio,

  • Diversi componenti possono condividere una coda multithreading senza bloccare l'una all'altra, richiedendo la creazione di meno thread.

  • Gli elementi di lavoro sono ottimizzati per evitare i commutatori di contesto se un evento è già impostato. Questo è più efficiente rispetto alla creazione di thread personalizzati per attendere gli eventi.

Quando si usa FMRealTimeClientEx, le applicazioni devono evitare la rotazione di thread e devono invece usare le code di lavoro. A questo scopo, le applicazioni devono implementare SetWorkQueueEx e non usare RegisterThreads e UnregisterThreads.

Quando la piattaforma Media Foundation viene inizializzata, crea una coda multithreading con l'identificatore MFASYNC_CALLBACK_QUEUE_MULTITHREADED.

Una coda multithreading non serializza gli elementi di lavoro. Ogni volta che un thread dal pool di thread diventa disponibile, viene inviato l'elemento di lavoro successivo nella coda. Il chiamante deve assicurarsi che il lavoro sia serializzato correttamente. Per semplificare questa operazione, Media Foundation definisce una coda di lavoro seriale. Una coda seriale esegue il wrapping di un'altra coda di lavoro, ma garantisce l'esecuzione completamente serializzata. L'elemento successivo della coda non viene inviato fino al completamento dell'elemento precedente.

Il codice seguente crea una coda serializzatore sulla coda multithreaded della piattaforma.

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

Più code seriali possono eseguire il wrapping della stessa coda multithreading. Le code seriali condividono quindi lo stesso pool di thread e l'esecuzione serializzata viene applicata all'interno di ogni coda.

Le code di lavoro standard esistenti prima della Windows 8 vengono ora implementate come code di lavoro seriali che esegue il wrapping della coda multithreaded della piattaforma. Questa modifica mantiene la compatibilità con le versioni precedenti.

Code di lavoro attività condivise

Per funzionare correttamente con l'utilità di pianificazione del kernel, deve essere presente una coda di lavoro multithreaded per ogni attività MMCSS usata. La piattaforma Media Foundation alloca questi elementi in base alle esigenze, fino a uno per ogni attività MMCSS, per processo. Per ottenere la coda di lavoro condivisa per un'attività MMCSS specifica, chiamare MFLockSharedWorkQueue e specificare il nome dell'attività. La funzione cerca il nome dell'attività in una tabella. Se una coda di lavoro non esiste già per questa attività, la funzione alloca una nuova coda di lavoro MT e lo aggiunge immediatamente all'attività MMCSS. Se esiste già una coda di lavoro per tale attività, la funzione restituisce l'identificatore della coda di lavoro esistente.

Coda di attesa

La coda di attesa è una coda di lavoro speciale della piattaforma che attende l'indicazione degli eventi. Se un componente deve attendere che venga segnalato un evento, può usare la coda di attesa anziché creare un thread di lavoro per attendere l'evento.

Per usare la coda di attesa, chiamare MFPutWaitingWorkItem. I parametri includono l'handle eventi e un puntatore IMFAsyncResult . Quando l'evento viene segnalato, la coda di attesa richiama il callback. C'è una singola coda di attesa della piattaforma; le applicazioni non possono creare code di attesa personalizzate.

Miglioramenti al supporto DI MMCSS

Le nuove funzioni della piattaforma Media Foundation seguenti si riferiscono a MMCSS.

Funzione Descrizione
MFBeginRegisterWorkQueueWithMMCSSEx Registra una coda di lavoro con MMCSS. Questa funzione include un parametro per specificare la priorità relativa del thread. Internamente, questo valore viene convertito in una chiamata a AvSetMmThreadPriority.
MFGetWorkQueueMMCSSPriority Esegue query sulla priorità di una coda di lavoro.
MFRegisterPlatformWithMMCSS Registra tutte le code di lavoro della piattaforma con un'attività MMCSS. Questa funzione è simile al metodo IMFWorkQueueServices::BeginRegisterPlatformWorkQueueWithMMCSS , ma può essere usato senza creare un'istanza della sessione multimediale. Inoltre, la funzione include un parametro per specificare la priorità del thread di base.

 

Le applicazioni che usano la sessione multimediale devono impostare l'attributo MF_TOPONODE_WORKQUEUE_MMCSS_CLASS su "Audio" per il ramo di rendering audio. Impostare l'attributo su "Playback" per il ramo di rendering video.

FMRealTimeClientEx

L'interfaccia FMRealTimeClientEx per sostituire FMRealTimeClient , per i componenti della pipeline che eseguono operazioni asincrone.

Metodo Descrizione
RegisterThreadsEx Notifica al componente di registrare i thread con MMCSS. Questo metodo equivale a FMRealTimeClient::RegisterThreads, ma aggiunge un parametro per la priorità del thread di base.
SetWorkQueueEx Notifica al componente di usare una coda di lavoro specifica. Questo metodo equivale a FMReadTimeClient::SetWorkQueue, ma aggiunge un parametro per la priorità dell'elemento di lavoro.
Annulla registrazioneThreads Notifica al componente di annullare la registrazione dei thread da MMCSS. Questo metodo è identico al metodo IMFRealTimeClient::UnregisterThreads .

 

I componenti della pipeline devono usare code di lavoro e non devono creare thread di lavoro, per i motivi seguenti:

  • Le code di lavoro aumentano meglio, perché usano i pool di thread del sistema operativo.
  • La piattaforma gestisce i dettagli della registrazione delle code di lavoro con MMCSS.
  • Un thread di lavoro può causare facilmente un deadlock difficile da eseguire nel debug.

È anche consigliabile usare la coda di lavoro del serializzatore se è necessario serializzare le operazioni asincrone.

Rami topologia

Se l'attributo MF_TOPONODE_WORKQUEUE_MMCSS_CLASS registra un ramo di topologia con MMCSS, in Windows 8 la sessione multimediale usa le code di lavoro MT condivise. Nelle versioni precedenti di Windows, la sessione multimediale ha allocato una nuova coda di lavoro.

Due nuovi attributi sono definiti per la registrazione di un ramo di topologia con MMCSS.

Attributo Descrizione
MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY Specifica la priorità del thread di base.
MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY Specifica la priorità dell'elemento di lavoro.

 

Consigli

  • Le applicazioni che usano la sessione multimediale devono impostare MF_TOPONODE_WORKQUEUE_MMCSS_CLASS su "Audio" per il ramo di rendering audio e "Riproduzione" per il ramo di rendering video.
  • Le applicazioni che usano la sessione multimediale devono chiamare FMWorkQueueServices::BeginRegisterTopologyWorkQueuesWithMMCSS nella topologia.
  • Per i componenti della pipeline, le code di lavoro sono consigliate anziché thread di lavoro. Se il componente usa code di lavoro o thread di lavoro, implementare IMFRealTimeClientEx.
  • Non creare code di lavoro private, in quanto ciò consente di sconfiggere lo scopo delle code di lavoro della piattaforma. Usare la coda multithreaded della piattaforma o una coda seriale che esegue il wrapping della coda multithreaded della piattaforma.
  • Se è necessario serializzare le operazioni asincrone, usare una coda seriale.

Riepilogo

Le API della piattaforma Media Foundation seguenti correlate ai thread e alle code di lavoro sono nuove per Windows 8.

Code di lavoro