Améliorations apportées à la file d’attente de travail et au threading

Cette rubrique décrit les améliorations apportées aux Windows 8 pour les files d’attente de travail et les threads dans la plateforme Microsoft Media Foundation.

Comportement de Windows 7

Cette section récapitule le comportement des files d’attente de travail Media Foundation dans Windows 7.

Files d’attente de travail

La plateforme Media Foundation crée plusieurs files d’attente de travail standard. Seuls deux sont documentés comme étant destinés à une utilisation générale de l’application :

  • MFASYNC_CALLBACK_QUEUE_STANDARD
  • MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION

Une application ou un composant peut allouer de nouvelles files d’attente de travail en appelant MFAllocateWorkQueue ou MFAllocateWorkQueueEx. La fonction MFAllocateWorkQueueEx définit deux types de file d’attente de travail :

  • MF_STANDARD_WORKQUEUE crée une file d’attente de travail sans boucle de message.
  • MF_WINDOW_WORKQUEUE crée une file d’attente de travail avec une boucle de message.

Pour mettre en file d’attente un élément de travail, appelez MFPutWorkItem ou MFPutWorkItemEx. La plateforme exécute l’élément de travail en appelant l’implémentation fournie par l’appelant d’IMFAsyncCallback. Dans Windows 7 et versions antérieures, la plateforme crée un thread par file d’attente de travail.

Prise en charge MMCSS

Le service MMCSS (Multimedia Class Scheduler Service ) gère les priorités des threads afin que les applications multimédias obtiennent régulièrement des tranches de temps processeur, sans refuser les ressources du processeur aux applications de priorité inférieure. MMCSS définit un ensemble de tâches qui ont différents profils d’utilisation du processeur. Lorsqu’un thread joint une tâche MMCSS, MMCSS définit la priorité du thread en fonction de plusieurs facteurs :

  • Priorité de base de la tâche, qui est définie dans le Registre.
  • Priorité de thread relative, qui est définie au moment de l’exécution en appelant AvSetMmThreadPriority.
  • Différentes caractéristiques d’exécution, telles que si l’application est au premier plan et combien de temps processeur est consommé par les threads dans chaque classe MMCSS.

Une application peut inscrire une file d’attente de travail auprès de MMCSS en appelant MFBeginRegisterWorkQueueWithMMCSS. Cette fonction prend un ID de file d’attente de travail, une classe MMCSS (nom de la tâche) et l’identificateur de tâche MMCSS. En interne, il appelle AvSetMmThreadCharacteristics avec le nom de la tâche et l’ID de tâche. Une fois qu’une file d’attente de travail est inscrite auprès de MMCSS, vous pouvez obtenir l’ID de classe et de tâche en appelant MFGetWorkQueueMMCSSClass et MFGetWorkQueueMMCSSTaskId.

La session multimédia offre un accès de niveau supérieur à ces API, via l’interface IMFWorkQueueServices . Cette interface fournit deux méthodes principales :

Méthode Description
BeginRegisterPlatformWorkQueueWithMMCSS Inscrit une file d’attente de travail avec une tâche MMCSS. Cette méthode est essentiellement un wrapper mince autour de MFBeginRegisterWorkQueueWithMMCSS, mais vous pouvez passer la valeur MFASYNC_CALLBACK_QUEUE_ALL pour inscrire toutes les files d’attente de travail de la plateforme à la fois.
BeginRegisterTopologyWorkQueuesWithMMCSS Inscrit une branche de la topologie avec une file d’attente de travail.

 

Pour inscrire une branche de topologie, procédez comme suit.

  1. Définissez l’attribut MF_TOPONODE_WORKQUEUE_ID sur le nœud source de la branche. Utilisez n’importe quelle valeur définie par l’application.
  2. Si vous le souhaitez, définissez le MF_TOPONODE_WORKQUEUE_MMCSS_CLASS pour joindre la file d’attente de travail à une tâche MMCSS.
  3. Appelez BeginRegisterTopologyWorkQueuesWithMMCSS sur la topologie résolue.

La session multimédia alloue une nouvelle file d’attente de travail pour chaque valeur unique de MF_TOPONODE_WORKQUEUE_ID. Pour chaque branche de topologie, des opérations de pipeline asynchrones sont effectuées sur la file d’attente de travail affectée à la branche.

IMFRealTimeClient

L’interface IMFRealTimeClient est destinée aux composants de pipeline qui créent leurs propres threads ou utilisent des files d’attente de travail pour les opérations asynchrones. La session multimédia utilise cette interface pour informer le composant de pipeline du comportement correct, comme suit :

  • Si le composant de pipeline crée un thread de travail, la méthode IMFRealTimeClient::RegisterThreads informe le composant de la classe MMCSS à joindre.
  • Si le composant de pipeline utilise une file d’attente de travail, la méthode IMFRealTimeClient::SetWorkQueue indique au composant la file d’attente de travail à utiliser.

En règle générale, un composant de pipeline utilise un thread ou une file d’attente de travail pour effectuer des tâches asynchrones, mais pas les deux.

améliorations Windows 8

Files d’attente de travail multithread

Dans Windows 8, Media Foundation prend en charge un nouveau type de file d’attente de travail appelé file d’attente multithread. Une file d’attente multithread utilise un pool de threads système pour distribuer les éléments de travail. La file d’attente multithread est mieux mise à l’échelle que les files d’attente monothread précédentes. Par exemple,

  • Plusieurs composants peuvent partager une file d’attente multithread sans se bloquer les uns les autres, ce qui nécessite la création de moins de threads.

  • Les éléments de travail sont optimisés pour éviter les commutateurs de contexte si un événement est déjà défini. Cela est plus efficace que la création de vos propres threads pour attendre les événements.

Lors de l’utilisation d’IMFRealTimeClientEx, les applications doivent éviter de faire tourner des threads et utiliser les files d’attente de travail. Pour ce faire, les applications doivent implémenter SetWorkQueueEx et ne pas utiliser RegisterThreads et UnregisterThreads.

Lorsque la plateforme Media Foundation est initialisée, elle crée une file d’attente multithread avec l’identificateur MFASYNC_CALLBACK_QUEUE_MULTITHREADED.

Une file d’attente multithread ne sérialise pas les éléments de travail. Chaque fois qu’un thread du pool de threads devient disponible, l’élément de travail suivant de la file d’attente est distribué. L’appelant doit s’assurer que le travail est sérialisé correctement. Pour faciliter cela, Media Foundation définit une file d’attente de travail série. Une file d’attente série encapsule une autre file d’attente de travail, mais garantit une exécution entièrement sérialisée. L’élément suivant de la file d’attente n’est pas distribué tant que l’élément précédent n’est pas terminé.

Le code suivant crée une file d’attente de sérialiseur sur la file d’attente multithread de la plateforme.

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

Plusieurs files d’attente série peuvent encapsuler la même file d’attente multithread. Les files d’attente série partagent ensuite le même pool de threads, et l’exécution sérialisée est appliquée dans chaque file d’attente.

Les files d’attente de travail standard qui existaient avant Windows 8 sont désormais implémentées en tant que files d’attente de travail série qui encapsulent la file d’attente multithread de la plateforme. Cette modification préserve la compatibilité descendante.

Files d’attente de travail de tâches partagées

Pour fonctionner correctement avec le planificateur du noyau, il doit y avoir une file d’attente de travail multithread pour chaque tâche MMCSS que vous utilisez. La plateforme Media Foundation les alloue en fonction des besoins, jusqu’à une tâche MMCSS par processus. Pour obtenir la file d’attente de travail partagée pour une tâche MMCSS particulière, appelez MFLockSharedWorkQueue et spécifiez le nom de la tâche. La fonction recherche le nom de la tâche dans une table. S’il n’existe pas encore de file d’attente de travail pour cette tâche, la fonction alloue une nouvelle file d’attente de travail MT et la joint immédiatement à la tâche MMCSS. Si une file d’attente de travail existe déjà pour cette tâche, la fonction retourne l’identificateur de la file d’attente de travail existante.

File d’attente

La file d’attente est une file d’attente de travail de plateforme spéciale qui attend les événements à signaler. Si un composant doit attendre qu’un événement soit signalé, il peut utiliser la file d’attente au lieu de créer un thread de travail pour attendre l’événement.

Pour utiliser la file d’attente, appelez MFPut WaitingWorkItem. Les paramètres incluent le handle d’événement et un pointeur IMFAsyncResult . Lorsque l’événement est signalé, la file d’attente appelle votre rappel. Il existe une seule file d’attente de plateforme ; les applications ne peuvent pas créer leurs propres files d’attente.

Améliorations apportées à la prise en charge de MMCSS

Les nouvelles fonctions de plateforme Media Foundation suivantes sont liées à MMCSS.

Fonction Description
MFBeginRegisterWorkQueueWithMMCSSEx Inscrit une file d’attente de travail auprès de MMCSS. Cette fonction inclut un paramètre pour spécifier la priorité de thread relative. En interne, cette valeur est traduite en un appel à AvSetMmThreadPriority.
MFGetWorkQueueMMCSSPriority Interroge la priorité d’une file d’attente de travail.
MFRegisterPlatformWithMMCSS Inscrit toutes les files d’attente de travail de la plateforme avec une tâche MMCSS. Cette fonction est similaire à la méthode IMFWorkQueueServices::BeginRegisterPlatformWorkQueueWithMMCSS, mais elle peut être utilisée sans créer de instance de la session multimédia. En outre, la fonction inclut un paramètre pour spécifier la priorité du thread de base.

 

Les applications qui utilisent la session multimédia doivent définir l’attribut MF_TOPONODE_WORKQUEUE_MMCSS_CLASS sur « Audio » pour la branche de rendu audio. Définissez l’attribut sur « Lecture » pour la branche de rendu vidéo.

IMFRealTimeClientEx

L’interface IMFRealTimeClientEx remplace IMFRealTimeClient pour les composants de pipeline qui effectuent des opérations asynchrones.

Méthode Description
RegisterThreadsEx Avertit le composant d’inscrire ses threads auprès de MMCSS. Cette méthode est équivalente à IMFRealTimeClient::RegisterThreads, mais elle ajoute un paramètre pour la priorité du thread de base.
SetWorkQueueEx Avertit le composant d’utiliser une file d’attente de travail spécifique. Cette méthode est équivalente à IMFReadTimeClient::SetWorkQueue, mais elle ajoute un paramètre pour la priorité de l’élément de travail.
UnregisterThreads Avertit le composant d’annuler l’inscription de ses threads auprès de MMCSS. Cette méthode est identique à la méthode IMFRealTimeClient::UnregisterThreads .

 

Les composants de pipeline doivent utiliser des files d’attente de travail et ne doivent pas créer de threads de travail, pour les raisons suivantes :

  • Les files d’attente de travail sont mieux mises à l’échelle, car elles utilisent les pools de threads de système d’exploitation.
  • La plateforme gère les détails de l’inscription des files d’attente de travail auprès de MMCSS.
  • Un thread de travail peut facilement provoquer un interblocage difficile à déboguer.

En outre, envisagez d’utiliser la file d’attente de travail du sérialiseur si vous devez sérialiser vos opérations asynchrones.

Branches de topologie

Si l’attribut MF_TOPONODE_WORKQUEUE_MMCSS_CLASS inscrit une branche de topologie auprès de MMCSS, dans Windows 8 la session multimédia utilise les files d’attente de travail MT partagées. Dans les versions antérieures de Windows, la session multimédia a alloué une nouvelle file d’attente de travail.

Deux nouveaux attributs sont définis pour l’inscription d’une branche de topologie auprès de MMCSS.

Attribut Description
MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY Spécifie la priorité du thread de base.
MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY Spécifie la priorité de l’élément de travail.

 

Recommandations

  • Les applications qui utilisent la session multimédia doivent définir MF_TOPONODE_WORKQUEUE_MMCSS_CLASS sur « Audio » pour la branche de rendu audio et « Lecture » pour la branche de rendu vidéo.
  • Les applications qui utilisent la session multimédia doivent appeler IMFWorkQueueServices::BeginRegisterTopologyWorkQueuesWithMMCSS sur la topologie.
  • Pour les composants de pipeline, les files d’attente de travail sont recommandées au lieu des threads de travail. Si le composant utilise des files d’attente de travail ou des threads de travail, implémentez IMFRealTimeClientEx.
  • Ne créez pas de files d’attente de travail privées, car cela va à l’encontre de l’objectif des files d’attente de travail de la plateforme. Utilisez la file d’attente multithread de la plateforme ou une file d’attente série qui encapsule la file d’attente multithread de la plateforme.
  • Si vous devez sérialiser des opérations asynchrones, utilisez une file d’attente série.

Récapitulatif

Les API de plateforme Media Foundation suivantes qui se rapportent aux threads et aux files d’attente de travail sont nouvelles pour Windows 8.

Files d’attente de travail