Accueil
Rechercher:
sur developpez.com sur les forums
Forums | Tutoriels | F.A.Q's | Participez | Hébergement | Contacts
Club Emploi Blogs   TV   Dév. Web PHP XML Python Autres 2D-3D-Jeux Sécurité Windows Linux PC Mac
Accueil Conception Java DotNET Visual Basic  C  C++ Delphi MS-Office SQL & SGBD Oracle  4D  Business Intelligence
FORUMS C FAQs C TUTORIELS C LIVRES C COMPILATEURS C SOURCES GTK+

Tutorial d'initiation
A la programmation avec l'API Windows

Tutorial d'initiation a la programmation Windows avec Microsoft Visual C++
PrécédentIndexSuivant

Chapitre 5

Le multithreading

8. Communication inter-threads

Cours théorique :

La communication inter-threads permet aux différent threads d'une application de dialoguer entre eux. Comme la réception des messages peut poser problème, on tentera généralement de réduire au minimum la communication inter-threads et donc de réaliser des threads aussi indépendants que possible.

Outre les fonctions de synchronisation qui ne sont pas à proprement parler des fonctions de communication, il existe deux moyens principaux de communication : les variables globales et les messages. Les variables globales sont un moyen de communication facile à mettre en place. Toutefois, leur utilisation devra être faite avec rigueur pour éviter des problèmes dus à l'accès de variables partagées. De plus dans certains cas, l'utilisation de variables globales peut nuire aux performances.

Une variable globale ne doit jamais être utilisée comme moyen de synchronisation. En effet, il est possible de placer la valeur d'une variable globale à 0 et d'effectuer une boucle avec un test sur cette variable de manière à attendre tant que la valeur reste à 0. Un second thread peut alors débloquer l'attente en modifiant la valeur de cette variable globale. Bien que fonctionnant, cette méthode ne devra jamais être utilisée car elle provoque une forte charge processeur inutile. Dans ce cas, les fonctions de synchronisation devront être utilisées car elles permettent de laisser l'accès processeur au reste du système tant que le thread est en attente.

De plus, deux threads ne doivent jamais accéder en écriture à une même variable globale. Ce type d'accès peut provoquer des plantages dus à la manière dont les variables globales sont utilisées (ces variables sont parfois placées dans des registres pour optimisation). L'utilisation de variables globales pour la communication inter-threads implique une communication à sens unique. Un thread accède à cette variable en écriture et les autres threads réagissent en fonction de cette valeur. Une telle utilisation ne posera pas de problèmes. Le partage de données mémoire en écriture implique des précautions particulières comme la synchronisation.

Les variables globales pourront donc être utilisées comme drapeau. Par exemple pour signifier à un thread qu'il doit se terminer. Si le thread effectue une boucle, on peut placer dans cette boucle un test sur la variable globale. Le thread principal place cette variable à une valeur principale au moment de quitter, ce qui provoque l'arrêt des autres threads. Notons tout de même que le thread principale devra attendre que l'ensemble des threads ait terminé avant de stopper l'application. En effet, l'arrêt de l'application provoque une fermeture de tous les threads en cours (ce qui revient à un appel de TerminateThread() ). Il faudra donc placer un système d'attente dans le thread principal (fonctionnant via d'autres variables globales ou par un système de messages de notification).

L'utilisation de variables globales est donc une méthode rapide de communication. Toutefois cette méthode est soumise à un certain nombre de contraintes qui ne doivent surtout pas être ignorées.

Les messages constituent la deuxième méthode de communication. La fonction PostThreadMessage() permet d'envoyer des messages à un thread, même si celui-ci ne gère pas de fenêtres. Le thread pourra alors utiliser les fonctions GetMessage() ou PeekMessage() pour récupérer les messages. Bien entendu, il sera inutile d'utiliser les fonctions TranslateMessage() et DispatchMessage() puisque ces messages ne sont pas destinés à des fenêtres.

Il existe plusieurs méthodes pour créer des messages personnalisés. Tout d'abord, il est possible de définir une constante au niveau du préprocesseur (#define). Les valeurs valides pour les messages définis par l'utilisateur doivent être compris entre les valeurs WM_USER et 0x7FFF. La constante WM_USER est définie dans les headers Windows.

La deuxième méthode consiste à utiliser la fonction RegisterWindowMessage(). Cette fonction retourne une valeur utilisable pour un message en fonction d'une chaîne de caractère. Le système garantit l'unicité du message en fonction de la chaîne de caractère. Si deux applications distinctes utilisent cette fonction avec la même chaîne, elles obtiendront la même valeur. Cette fonction doit donc seulement être utilisée dans le cadre de la communication inter-applications, c'est à dire au niveau système. Si les messages sont locaux à l'application, il est recommandé de définir des constantes.

Si un thread désire communiquer une plus grande quantité d'information, il peut joindre au message 2 valeurs (lParam et wParam). Deux choix sont alors possibles. Utiliser ces valeurs comme paramètres ou joindre un pointeur. La méthode à utiliser pour joindre un pointeur est la suivante : le thread qui poste le message alloue dynamiquement de la mémoire et poste le pointeur. Le thread émetteur ne doit pas désallouer cette mémoire. C'est le thread récepteur qui s'occupera de la désallocation de la mémoire. Cette méthode assure que le pointeur sera toujours valide à la réception du message.


PrécédentIndexSuivant

Responsable bénévole de la rubrique C : Arnaud Feltz (buchs) - Contacter par EMail :
Vos questions techniques : forum d'entraide C - Publiez vos articles, tutoriels et cours
et rejoignez-nous dans l'équipe de rédaction du club d'entraide des développeurs francophones
Nous contacter - Copyright © 2000-2008 www.developpez.com - Legal informations.