Melhorias na fila de trabalho e no threading

Este tópico descreve melhorias no Windows 8 para filas de trabalho e threading na plataforma microsoft media foundation.

Comportamento do Windows 7

Esta seção resume o comportamento das filas de trabalho do Media Foundation no Windows 7.

Filas de Trabalho

A plataforma Media Foundation cria várias filas de trabalho padrão. Apenas dois estão documentados como sendo para uso geral do aplicativo:

  • MFASYNC_CALLBACK_QUEUE_STANDARD
  • MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION

Um aplicativo ou componente pode alocar novas filas de trabalho chamando MFAllocateWorkQueue ou MFAllocateWorkQueueEx. A função MFAllocateWorkQueueEx define dois tipos de fila de trabalho:

  • MF_STANDARD_WORKQUEUE cria uma fila de trabalho sem um loop de mensagem.
  • MF_WINDOW_WORKQUEUE cria uma fila de trabalho com um loop de mensagem.

Para enfileirar um item de trabalho, chame MFPutWorkItem ou MFPutWorkItemEx. A plataforma executa o item de trabalho invocando a implementação fornecida pelo chamador de IMFAsyncCallback. No Windows 7 e versões anteriores, a plataforma cria um thread por fila de trabalho.

Suporte do MMCSS

O MMCSS ( Multimedia Class Scheduler Service ) gerencia prioridades de thread para que os aplicativos multimídia obtenham fatias regulares de tempo de CPU, sem negar recursos de CPU a aplicativos de menor prioridade. O MMCSS define um conjunto de tarefas que têm perfis de utilização de CPU diferentes. Quando um thread ingressa em uma tarefa do MMCSS, o MMCSS define a prioridade do thread com base em vários fatores:

  • A prioridade base da tarefa, que é definida no registro.
  • A prioridade relativa do thread, que é definida em tempo de execução chamando AvSetMmThreadPriority.
  • Várias características de tempo de execução, como se o aplicativo está em primeiro plano e quanto tempo de CPU está sendo consumido pelos threads em cada classe MMCSS.

Um aplicativo pode registrar uma fila de trabalho com o MMCSS chamando MFBeginRegisterWorkQueueWithMMCSS. Essa função usa uma ID de fila de trabalho, uma classe MMCSS (nome da tarefa) e o identificador de tarefa MMCSS. Internamente, ele chama AvSetMmThreadCharacteristics com o nome da tarefa e a ID da tarefa. Depois que uma fila de trabalho é registrada com o MMCSS, você pode obter a classe e a ID da tarefa chamando MFGetWorkQueueMMCSSClass e MFGetWorkQueueMMCSSTaskId.

A Sessão de Mídia fornece acesso de nível um pouco mais alto a essas APIs, por meio da interface IMFWorkQueueServices . Essa interface fornece dois métodos principais:

Método Descrição
BeginRegisterPlatformWorkQueueWithMMCSS Registra uma fila de trabalho com uma tarefa do MMCSS. Esse método é essencialmente um wrapper fino em torno de MFBeginRegisterWorkQueueWithMMCSS, mas você pode passar o valor MFASYNC_CALLBACK_QUEUE_ALL para registrar todas as filas de trabalho da plataforma de uma só vez.
BeginRegisterTopologyWorkQueuesWithMMCSS Registra um branch da topologia com uma fila de trabalho.

 

Para registrar um branch de topologia, faça o seguinte.

  1. Defina o atributo MF_TOPONODE_WORKQUEUE_ID no nó de origem para o branch. Use qualquer valor definido pelo aplicativo.
  2. Opcionalmente, defina o MF_TOPONODE_WORKQUEUE_MMCSS_CLASS para unir a fila de trabalho a uma tarefa do MMCSS.
  3. Chame BeginRegisterTopologyWorkQueuesWithMMCSS na topologia resolvida.

A Sessão de Mídia aloca uma nova fila de trabalho para cada valor exclusivo de MF_TOPONODE_WORKQUEUE_ID. Para cada branch de topologia, as operações de pipeline assíncronas são executadas na fila de trabalho atribuída ao branch.

IMFRealTimeClient

A interface IMFRealTimeClient destina-se a componentes de pipeline que criam seus próprios threads ou usam filas de trabalho para operações assíncronas. A Sessão de Mídia usa essa interface para notificar o componente de pipeline sobre o comportamento correto, da seguinte maneira:

Normalmente, um componente de pipeline usa um thread ou uma fila de trabalho para executar tarefas assíncronas, mas não ambas.

Melhorias do Windows 8

Filas de trabalho multithread

No Windows 8, o Media Foundation dá suporte a um novo tipo de fila de trabalho chamado fila multithread. Uma fila multithreaded usa um pool de threads do sistema para expedir itens de trabalho. A fila multithread é dimensionada melhor do que as filas de thread único anteriores. Por exemplo,

  • Vários componentes podem compartilhar uma fila multithread sem bloquear uns aos outros, exigindo a criação de menos threads.

  • Os itens de trabalho são otimizados para evitar mudanças de contexto se um evento já estiver definido. Isso é mais eficiente do que criar seus próprios threads para aguardar eventos.

Ao usar IMFRealTimeClientEx, os aplicativos devem evitar a rotação de threads e, em vez disso, devem usar as filas de trabalho. Para fazer isso, os aplicativos devem implementar SetWorkQueueEx e não usar RegisterThreads e UnregisterThreads.

Quando a plataforma Media Foundation é inicializada, ela cria uma fila multithread com o identificador MFASYNC_CALLBACK_QUEUE_MULTITHREADED.

Uma fila multithreaded não serializa itens de trabalho. Sempre que um thread do pool de threads estiver disponível, o próximo item de trabalho na fila será expedido. O chamador deve garantir que o trabalho seja serializado corretamente. Para facilitar isso, o Media Foundation define uma fila de trabalho serial. Uma fila serial encapsula outra fila de trabalho, mas garante a execução totalmente serializada. O próximo item na fila não é expedido até que o item anterior seja concluído.

O código a seguir cria uma fila de serializadores na fila multithread da plataforma.

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

Mais de uma fila serial pode encapsular a mesma fila multithreaded. Em seguida, as filas seriais compartilham o mesmo pool de threads e a execução serializada é imposta em cada fila.

As filas de trabalho padrão que existiam antes Windows 8 agora são implementadas como filas de trabalho serial que encapsulam a fila multithread da plataforma. Essa alteração preserva a compatibilidade com versões anteriores.

Filas de trabalho de tarefas compartilhadas

Para trabalhar corretamente com o agendador de kernel, deve haver uma fila de trabalho multithread para cada tarefa MMCSS que você usa. A plataforma Media Foundation os aloca conforme necessário, até um por tarefa MMCSS, por processo. Para obter a fila de trabalho compartilhada para uma tarefa específica do MMCSS, chame MFLockSharedWorkQueue e especifique o nome da tarefa. A função pesquisa o nome da tarefa em uma tabela. Se uma fila de trabalho ainda não existir para essa tarefa, a função alocará uma nova fila de trabalho mt e a unirá imediatamente à tarefa MMCSS. Se já existir uma fila de trabalho para essa tarefa, a função retornará o identificador da fila de trabalho existente.

Fila de Espera

A fila de espera é uma fila de trabalho de plataforma especial que aguarda que os eventos sejam sinalizados. Se um componente precisar aguardar a sinalização de um evento, ele poderá usar a fila de espera em vez de criar um thread de trabalho para aguardar o evento.

Para usar a fila de espera, chame MFPutWaitingWorkItem. Os parâmetros incluem o identificador de evento e um ponteiro IMFAsyncResult . Quando o evento é sinalizado, a fila de espera invoca o retorno de chamada. Há uma fila de espera de plataforma única; os aplicativos não podem criar suas próprias filas de espera.

Aprimoramentos no suporte ao MMCSS

As novas funções de plataforma do Media Foundation a seguir estão relacionadas ao MMCSS.

Função Descrição
MFBeginRegisterWorkQueueWithMMCSSEx Registra uma fila de trabalho com o MMCSS. Essa função inclui um parâmetro para especificar a prioridade relativa do thread. Internamente, esse valor é convertido em uma chamada para AvSetMmThreadPriority.
MFGetWorkQueueMMCSSPriority Consulta a prioridade de uma fila de trabalho.
MFRegisterPlatformWithMMCSS Registra todas as filas de trabalho da plataforma com uma tarefa MMCSS. Essa função é semelhante ao método IMFWorkQueueServices::BeginRegisterPlatformWorkQueueWithMMCSS , mas pode ser usada sem criar uma instância da Sessão de Mídia. Além disso, a função inclui um parâmetro para especificar a prioridade do thread base.

 

Os aplicativos que usam a Sessão de Mídia devem definir o atributo MF_TOPONODE_WORKQUEUE_MMCSS_CLASS como "Áudio" para o branch de renderização de áudio. Defina o atributo como "Reprodução" para o branch de renderização de vídeo.

IMFRealTimeClientEx

A interface IMFRealTimeClientEx para substitui IMFRealTimeClient, para componentes de pipeline que executam operações assíncronas.

Método Descrição
RegisterThreadsEx Notifica o componente para registrar seus threads com o MMCSS. Esse método é equivalente a IMFRealTimeClient::RegisterThreads, mas adiciona um parâmetro para a prioridade de thread base.
SetWorkQueueEx Notifica o componente para usar uma fila de trabalho específica. Esse método é equivalente a IMFReadTimeClient::SetWorkQueue, mas adiciona um parâmetro para a prioridade do item de trabalho.
UnregisterThreads Notifica o componente para cancelar o registro de seus threads do MMCSS. Esse método é idêntico ao método IMFRealTimeClient::UnregisterThreads .

 

Os componentes de pipeline devem usar filas de trabalho e não devem criar threads de trabalho pelos seguintes motivos:

  • As filas de trabalho são dimensionadas melhor, pois usam os pools de threads do sistema operacional.
  • A plataforma lida com os detalhes do registro de filas de trabalho com o MMCSS.
  • Um thread de trabalho pode facilmente causar um deadlock difícil de depurar.

Além disso, considere usar a fila de trabalho do serializador se você precisar serializar suas operações assíncronas.

Branches de topologia

Se o atributo MF_TOPONODE_WORKQUEUE_MMCSS_CLASS registrar um branch de topologia com o MMCSS, em Windows 8 a Sessão de Mídia usará as filas de trabalho de MT compartilhadas. Em versões anteriores do Windows, a Sessão de Mídia alocava uma nova fila de trabalho.

Dois novos atributos são definidos para registrar um branch de topologia com o MMCSS.

Atributo Descrição
MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY Especifica a prioridade do thread base.
MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY Especifica a prioridade do item de trabalho.

 

Recomendações

  • Os aplicativos que usam a Sessão de Mídia devem definir MF_TOPONODE_WORKQUEUE_MMCSS_CLASS como "Áudio" para o branch de renderização de áudio e "Reprodução" para o branch de renderização de vídeo.
  • Os aplicativos que usam a Sessão de Mídia devem chamar IMFWorkQueueServices::BeginRegisterTopologyWorkQueuesWithMMCSS na topologia.
  • Para componentes de pipeline, as filas de trabalho são recomendadas em vez de threads de trabalho. Se o componente usar filas de trabalho ou threads de trabalho, implemente IMFRealTimeClientEx.
  • Não crie filas de trabalho privadas, pois isso derrota a finalidade das filas de trabalho da plataforma. Use a fila multithreaded da plataforma ou uma fila serial que encapsula a fila multithread da plataforma.
  • Se você precisar serializar operações assíncronas, use uma fila serial.

Resumo

As SEGUINTEs APIs de plataforma do Media Foundation relacionadas a threads e filas de trabalho são novas para Windows 8.

Filas de Trabalho