Condividi tramite


Miglioramenti alla coda di lavoro e al threading

Questo argomento descrive i miglioramenti apportati a 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 IMFAsyncCallback. In Windows 7 e versioni precedenti, la piattaforma crea un thread per ogni coda di lavoro.

Supporto DI MMCSS

Il Servizio di pianificazione classi multimediali (MMCSS) gestisce le priorità dei thread in modo che le applicazioni multimediali ottengano regolari sezioni di tempo 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 unisce 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 quanto tempo cpu viene utilizzato 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 la classe e l'ID attività chiamando MFGetWorkQueueMMCSSClass e MFGetWorkQueueMMCSSTaskId.

L'sessione multimediale fornisce accesso di livello superiore a queste API tramite l'interfaccia IMFWorkQueueServices. Questa interfaccia fornisce due metodi principali:

Metodo Descrizione
BeginRegisterPlatformWorkQueueWithMMCSS Registra una coda di lavoro con un'attività MMCSS. Questo metodo è essenzialmente un wrapper sottile intorno 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 il MF_TOPONODE_WORKQUEUE_MMCSS_CLASS per unire 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 asincrona vengono eseguite nella coda di lavoro assegnata al ramo.

IMFRealTimeClient

L'interfacciaIMFRealTimeClientè destinata ai componenti della pipeline che creano i propri thread o usano code di lavoro per 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 di Windows 8

Code di lavoro multithreading

In Windows 8 Media Foundation supporta un nuovo tipo di coda di lavoro denominato coda multithreading . Una coda multithreading usa un pool di thread di sistema per inviare gli elementi di lavoro. La coda multithreading viene ridimensionata in modo migliore rispetto alle code a thread singolo precedenti. Per esempio

  • Diversi componenti possono condividere una coda multithreading senza bloccarsi l'una dall'altra, richiedendo la creazione di un numero inferiore di thread.

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

Quando si usa IMFRealTimeClientEx, le applicazioni devono evitare di avviare thread e usare invece le code di lavoro. A tale 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 nella coda non viene inviato fino al completamento dell'elemento precedente.

Il codice seguente crea una coda di serializzatori sulla coda multithreading 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 di Windows 8 vengono ora implementate come code di lavoro seriali che eseguono il wrapping della coda multithreading 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 multithreading per ogni attività MMCSS usata. La piattaforma Media Foundation le alloca in base alle esigenze, fino a una per ogni attività MMCSS, per processo. Per ottenere la coda di lavoro condivisa per una determinata attività MMCSS, chiamare MFLockSharedWorkQueue e specificare il nome dell'attività. La funzione cerca il nome dell'attività in una tabella. Se non esiste già una coda di lavoro per questa attività, la funzione alloca una nuova coda di lavoro MT e la aggiunge immediatamente all'attività MMCSS. Se per tale attività esiste già una coda di lavoro, 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 la segnalazione 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 di 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 MMCSS

Le nuove funzioni della piattaforma Media Foundation seguenti sono correlate 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 una 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 usata 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.

IMFRealTimeClientEx

L'interfaccia IMFRealTimeClientEx per sostituire IMFRealTimeClient, 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 IMFRealTimeClient::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 IMFReadTimeClient::SetWorkQueue, ma aggiunge un parametro per la priorità dell'elemento di lavoro.
unregisterThreads 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 di livello, 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 di cui è difficile eseguire il debug.

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

Rami della topologia

Se l'attributo MF_TOPONODE_WORKQUEUE_MMCSS_CLASS registra un ramo della 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.

Per la registrazione di un ramo di topologia con MMCSS vengono definiti due nuovi attributi.

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 IMFWorkQueueServices::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ò sconfigge lo scopo delle code di lavoro della piattaforma. Usare la coda multithreading della piattaforma o una coda seriale che esegue il wrapping della coda multithreading della piattaforma.
  • Se è necessario serializzare le operazioni asincrone, usare una coda seriale.

Sommario

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

code di lavoro