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

В этом разделе описываются улучшения 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 значение Audio для ветви отрисовки звука. Задайте для атрибута значение "Воспроизведение" для ветви отрисовки видео.

IMFRealTimeClientEx

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

Метод Описание
RegisterThreadsEx Уведомляет компонент о регистрации потоков в MMCSS. Этот метод эквивалентен IMFRealTimeClient::RegisterThreads, но добавляет параметр для приоритета базового потока.
SetWorkQueueEx Уведомляет компонент об использовании определенной рабочей очереди. Этот метод эквивалентен IMFReadTimeClient::SetWorkQueue, но добавляет параметр для приоритета рабочего элемента.
Отмена регистрации Уведомляет компонент об отмене регистрации потоков из 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.

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