Улучшения рабочих очередей и потоков

В этом разделе описываются улучшения в Windows 8 для рабочих очередей и потоков на платформе Microsoft Media Foundation.

Поведение Windows 7

В этом разделе описывается поведение рабочих очередей Media Foundation в Windows 7.

Рабочие очереди

Платформа Media Foundation создает несколько стандартных рабочих очередей. Только два из них задокументированы как доступные для общего использования приложения:

  • MFASYNC_CALLBACK_QUEUE_STANDARD
  • MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION

Приложение или компонент может выделять новые рабочие очереди, вызывая MFAllocateWorkQueue или MFAllocateWorkQueueEx. Функция MFAllocateWorkQueueEx определяет два типа рабочей очереди:

  • MF_STANDARD_WORKQUEUE создает рабочую очередь без цикла сообщений.
  • MF_WINDOW_WORKQUEUE создает рабочую очередь с циклом сообщений.

Чтобы поместить рабочий элемент в очередь, вызовите MFPutWorkItem или MFPutWorkItemEx. Платформа выполняет рабочий элемент путем вызова реализации IMFAsyncCallback, предоставленной вызывающим абонентом. В Windows 7 и более ранних версиях платформа создает по одному потоку для каждой рабочей очереди.

Поддержка MMCSS

Служба мультимедийного планировщика классов (MMCSS) управляет приоритетами потоков, чтобы мультимедийные приложения получили регулярные срезы времени ЦП, не запрещая ресурсы ЦП приложениям с более низким приоритетом. MMCSS определяет набор задач с разными профилями использования ЦП. Когда поток присоединяется к задаче MMCSS, MMCSS задает приоритет потока на основе нескольких факторов:

  • Базовый приоритет задачи, заданный в реестре.
  • Относительный приоритет потока, который задается во время выполнения путем вызова AvSetMmThreadPriority.
  • Различные характеристики среды выполнения, например, находится ли приложение на переднем плане и сколько времени ЦП занимает потоки в каждом классе MMCSS.

Приложение может зарегистрировать рабочую очередь в MMCSS, вызвав MFBeginRegisterWorkQueueWithMMCSS. Эта функция принимает идентификатор рабочей очереди, класс MMCSS (имя задачи) и идентификатор задачи MMCSS. Внутренне он вызывает AvSetMmThreadCharacteristics с именем и идентификатором задачи. После регистрации рабочей очереди в MMCSS можно получить идентификатор класса и задачи, вызвав MFGetWorkQueueMMCSSClass и MFGetWorkQueueMMCSSTaskId.

Сеанс мультимедиа обеспечивает более высокий уровень доступа к этим API через интерфейс IMFWorkQueueServices. Этот интерфейс предоставляет два основных метода:

Метод Описание
BeginRegisterPlatformWorkQueueWithMMCSS Регистрирует рабочую очередь с задачей MMCSS. По сути, этот метод является тонкой оболочкой для MFBeginRegisterWorkQueueWithMMCSS, но вы можете передать значение MFASYNC_CALLBACK_QUEUE_ALL , чтобы зарегистрировать все рабочие очереди платформы одновременно.
BeginRegisterTopologyWorkQueuesWithMMCSS Регистрирует ветвь топологии в рабочей очереди.

 

Чтобы зарегистрировать ветвь топологии, выполните следующие действия.

  1. Задайте атрибут MF_TOPONODE_WORKQUEUE_ID на исходном узле для ветви. Используйте любое значение, определенное приложением.
  2. При необходимости задайте MF_TOPONODE_WORKQUEUE_MMCSS_CLASS для присоединения рабочей очереди к задаче MMCSS.
  3. Вызовите BeginRegisterTopologyWorkQueuesWithMMCSS для разрешенной топологии.

Сеанс мультимедиа выделяет новую рабочую очередь для каждого уникального значения MF_TOPONODE_WORKQUEUE_ID. Для каждой ветви топологии асинхронные операции конвейера выполняются в рабочей очереди, назначенной ветви.

IMFRealTimeClient

Интерфейс IMFRealTimeClient предназначен для компонентов конвейера, которые либо создают собственные потоки, либо используют рабочие очереди для асинхронных операций. Сеанс мультимедиа использует этот интерфейс для уведомления компонента конвейера о правильном поведении, как показано ниже.

  • Если компонент конвейера создает рабочий поток, метод IMFRealTimeClient::RegisterThreads уведомляет компонент, к которому нужно присоединить класс MMCSS.
  • Если компонент конвейера использует рабочую очередь, метод IMFRealTimeClient::SetWorkQueue сообщает компоненту, какую рабочую очередь использовать.

Как правило, компонент конвейера использует поток или рабочую очередь для выполнения асинхронных задач, но не одновременно.

Улучшения Windows 8

Многопоточные рабочие очереди

В Windows 8 Media Foundation поддерживает новый тип рабочей очереди, называемый многопоточной очередью. Многопоточность очереди использует пул системных потоков для отправки рабочих элементов. Многопоточная очередь масштабируется лучше, чем предыдущие однопоточные очереди. Например,

  • Несколько компонентов могут совместно использовать многопоточные очереди, не блокируя друг друга, что требует создания меньшего количества потоков.

  • Рабочие элементы оптимизированы, чтобы избежать переключения контекста, если событие уже задано. Это более эффективно, чем создание собственных потоков для ожидания событий.

При использовании IMFRealTimeClientEx приложения должны избегать вращения потоков и использовать рабочие очереди. Для этого приложения должны реализовывать SetWorkQueueEx и не использовать RegisterThreads и UnregisterThreads.

При инициализации платформы Media Foundation создается многопоточность с идентификатором MFASYNC_CALLBACK_QUEUE_MULTITHREADED.

Многопоточная очередь не сериализует рабочие элементы. Всякий раз, когда поток из пула потоков становится доступным, отправляется следующий рабочий элемент в очереди. Вызывающий объект должен убедиться, что работа сериализована правильно. Чтобы упростить эту задачу, Media Foundation определяет последовательную рабочую очередь. Последовательная очередь упаковывает другую рабочую очередь, но гарантирует полное сериализованное выполнение. Следующий элемент в очереди не отправляется до завершения предыдущего элемента.

Следующий код создает очередь сериализатора в многопоточной очереди платформы.

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

Несколько последовательных очередей могут обертывать одну и ту же многопоточность. Затем последовательные очереди совместно используют один пул потоков, и сериализованное выполнение применяется в каждой очереди.

Стандартные рабочие очереди, существовавшие до Windows 8, теперь реализуются как последовательные рабочие очереди, которые упаковывают многопоточные очереди платформы. Это изменение сохраняет обратную совместимость.

Общие рабочие очереди задач

Для правильной работы с планировщиком ядра для каждой используемой задачи MMCSS должна быть одна многопоточность. Платформа Media Foundation выделяет их по мере необходимости( до одного на каждую задачу MMCSS для каждого процесса). Чтобы получить общую рабочую очередь для конкретной задачи MMCSS, вызовите MFLockSharedWorkQueue и укажите имя задачи. Функция ищет имя задачи в таблице. Если рабочая очередь еще не существует для этой задачи, функция выделяет новую рабочую очередь MT и немедленно присоединяет ее к задаче MMCSS. Если для этой задачи уже существует рабочая очередь, функция возвращает идентификатор существующей рабочей очереди.

Очередь ожидания

Очередь ожидания — это специальная рабочая очередь платформы, которая ожидает передачи сигналов о событиях. Если компоненту необходимо дождаться передачи сигнала о событии, он может использовать очередь ожидания вместо создания рабочего потока для ожидания события.

Чтобы использовать очередь ожидания, вызовите MFPutWaitingWorkItem. Параметры включают дескриптор события и указатель IMFAsyncResult . Когда событие подается, очередь ожидания вызывает обратный вызов. Существует одна очередь ожидания платформы; Приложения не могут создавать собственные очереди ожидания.

Улучшения поддержки MMCSS

Следующие новые функции платформы Media Foundation связаны с MMCSS.

Функция Описание
MFBeginRegisterWorkQueueWithMMCSSEx Регистрирует рабочую очередь в MMCSS. Эта функция включает параметр для указания относительного приоритета потока. Внутренне это значение преобразуется в вызов AvSetMmThreadPriority.
MFGetWorkQueueMMCSSPriority Запрашивает приоритет рабочей очереди.
MFRegisterPlatformWithMMCSS Регистрирует все рабочие очереди платформы с задачей MMCSS. Эта функция аналогична методу IMFWorkQueueServices::BeginRegisterPlatformWorkQueueWithMMCSS , но ее можно использовать без создания экземпляра сеанса мультимедиа. Кроме того, функция включает параметр для указания приоритета базового потока.

 

Приложения, использующие сеанс мультимедиа, должны задать для атрибута MF_TOPONODE_WORKQUEUE_MMCSS_CLASS значение "Звук" для ветви отрисовки звука. Присвойте атрибуту значение "Воспроизведение" для ветви отрисовки видео.

IMFRealTimeClientEx

Интерфейс IMFRealTimeClientEx заменяет IMFRealTimeClient для компонентов конвейера, выполняющих асинхронные операции.

Метод Описание
RegisterThreadsEx Уведомляет компонент о регистрации своих потоков в MMCSS. Этот метод эквивалентен IMFRealTimeClient::RegisterThreads, но добавляет параметр для приоритета базового потока.
SetWorkQueueEx Уведомляет компонент об использовании определенной рабочей очереди. Этот метод эквивалентен IMFReadTimeClient::SetWorkQueue, но добавляет параметр для приоритета рабочего элемента.
UnregisterThreads Уведомляет компонент о отмене регистрации потоков из MMCSS. Этот метод идентичен методу IMFRealTimeClient::UnregisterThreads .

 

Компоненты конвейера должны использовать рабочие очереди и не должны создавать рабочие потоки по следующим причинам:

  • Рабочие очереди лучше масштабируются, так как используют пулы потоков ОС.
  • Платформа обрабатывает сведения о регистрации рабочих очередей в MMCSS.
  • Рабочий поток может легко вызвать взаимоблокировку, которую трудно отлаживать.

Кроме того, рассмотрите возможность использования рабочей очереди сериализатора, если необходимо сериализовать асинхронные операции.

Ветви топологии

Если атрибут MF_TOPONODE_WORKQUEUE_MMCSS_CLASS регистрирует ветвь топологии в MMCSS, в Windows 8 сеанс мультимедиа использует общие рабочие очереди mt. В более ранних версиях Windows сеанс мультимедиа выделил новую рабочую очередь.

Для регистрации ветви топологии в MMCSS определены два новых атрибута.

attribute Описание
MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY Задает приоритет базового потока.
MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY Задает приоритет рабочего элемента.

 

Рекомендации

  • Приложения, использующие сеанс мультимедиа, должны задать для MF_TOPONODE_WORKQUEUE_MMCSS_CLASS значение "Звук" для ветви отрисовки звука и "Воспроизведение" для ветви отрисовки видео.
  • Приложения, использующие сеанс мультимедиа, должны вызывать IMFWorkQueueServices::BeginRegisterTopologyWorkQueuesWithMMCSS в топологии.
  • Для компонентов конвейера вместо рабочих потоков рекомендуется использовать рабочие очереди. Если компонент использует рабочие очереди или рабочие потоки, реализуйте IMFRealTimeClientEx.
  • Не создавайте частные рабочие очереди, так как это не по назначению рабочих очередей платформы. Используйте многопототочную очередь платформы или последовательную очередь, которая обертывает многопоточность платформы.
  • Если необходимо сериализовать асинхронные операции, используйте последовательную очередь.

Сводка

Следующие API-интерфейсы платформы Media Foundation, связанные с потоками и рабочими очередями, являются новыми для Windows 8.

Рабочие очереди