Tutorial d'initiation A la programmation avec l'API Windows
Tutorial d'initiation a la programmation Windows avec Microsoft Visual C++
Chapitre 5Le multithreading7. Récupération des messages
Cours théorique :
La récupération des messages peut avoir deux fonctions : récupérer les messages de communication liés à une fenêtre ou récupérer les messages de communication inter-thread. La réception des messages doit être effectuée de manière différente selon le type de messages. De manière générale, les messages associés à des fenêtres doivent être traités avec la fonction GetMessage() dans une boucle. Cette fonction permet de passer le contrôle aux autres threads du système dès que la file d'attente est vide. De cette manière les performances sont optimales. De plus, les messages associés aux fenêtres doivent être traités rapidement. L'utilisation de cette fonction dans une boucle permet donc un traitement rapide tout en conservant de bonnes performances.
Le traitement des messages dans le cadre de la communication inter-thread est différent (il sera vu plus en détail plus tard). Il concerne par exemple l'envoi d'un message d'abandon de la tâche courante. La fonction GetMessage() est très peu adaptée au traitement de ce type de messages car elle est bloquante. Le thread sera donc suspendu tant que la file d'attente sera vide. Un thread ne s'occupant pas de la réception des messages associés à une fenêtre a généralement une tâche bien précise à exécuter. Il serait donc absurde d'utiliser une fonction bloquante pour le traitement des messages. De plus, ces messages ne nécessitent pas un traitement rapide. On préférera donc utiliser la fonction PeekMessage() qui elle n'est pas bloquante. Il faudra donc utiliser cette fonction dans une boucle. Comme l'utilisation de cette fonction dans une boucle provoque de graves problèmes de performances, il ne faudra pas effectuer cette boucle trop fréquemment. Prenons l'exemple d'un thread gérant un transfert de fichier. Le transfert de fichier est réalisé par une boucle qui lit les données puis les écrit à une place différente. Selon la durée moyenne d'une boucle, on déterminera un intervalle d'appel de PeekMessage(). Par exemple, toutes les 100 itérations de la boucle principale, la fonction PeekMessage() sera appelée dans une boucle jusqu'à épuisement de la fille d'attente. Ce type de traitement est adapté à un faible nombre de messages, de manière à ne pas ralentir le travail de la boucle principale. En supposant que la durée moyenne d'une itération de la boucle soit de 5ms, les messages seront donc traités 2 fois par seconde. Si un message demandant l'arrêt de la tâche en cours est envoyé, il sera traité au plus 500ms plus tard, ce qui est très acceptable. De plus, cette technique ne nuit que très peu aux performances de la boucle principale puisque seulement une itération sur 100 sera sensiblement ralentie.
Si la rapidité du traitement des messages n'a que peu d'importance on pourra espacer les appels à PeekMessage() de manière à conserver autant que possibles les performances de la boucle principale. Cette fonction sera donc particulièrement adaptée au traitement de messages de notifications envoyés à des thread effectuant une tâche précise.
Dans le cas d'un thread effectuant des tâches 'sur commande' on préférera bien entendu la fonction bloquante GetMessage() puisque le thread sera en attente de tâche (et ne consommera donc pas de ressources).
|