Jc/md/lp-01/06Threads1. jc/md/lp-01/06Threads2 Objectif du chapitre Génération dune application...
-
Upload
blaise-bourdin -
Category
Documents
-
view
109 -
download
0
Transcript of Jc/md/lp-01/06Threads1. jc/md/lp-01/06Threads2 Objectif du chapitre Génération dune application...
jc/md/lp-01/06 Threads 1
Threads
jc/md/lp-01/06 Threads 2
Objectif du chapitre
• Génération d’une application avec thread– Création d’un thread– Identification d’un thread– Suspension/Reprise d’un thread– Destruction d’un thread– Contrôle de l’exécution
• Exemples de threads
jc/md/lp-01/06 Threads 3
Point de départ
• Partir d’une plate-forme de base pour émulateur de type « Industrial Controller »
• Construire (Build) la plate-forme
• Créer une application THREAD1 de type « Simple Windows CE Application »
jc/md/lp-01/06 Threads 4
Création de l’application
jc/md/lp-01/06 Threads 5
Application THREAD1
jc/md/lp-01/06 Threads 6
Platform Settings
jc/md/lp-01/06 Threads 7
Création d’un thread (1)
Fonction CreateThread
HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThreadId);
Valeur de retour : handle créé ou NULL
jc/md/lp-01/06 Threads 8
Création d’un thread (2) : arguments
lpThreadAttributes : NULL sous CE,
dwStackSize : taille de la pile du thread créé
lpStartAddress : pointeur sur le début du thread
lpParameter : pointe une variable pour le thread
dwCreationFlags : 0 pour démarrer le thread
lpThreadId : pointeur sur une variable qui reçoit l’identificateur de thread, le ThreadId
jc/md/lp-01/06 Threads 9
Suspend/Resume Thread
• Gestion du compteur associé au thread• Thread éligible quand ce compteur est nul• Pour suspendre un thread
DWORD SuspendThread( HANDLE hThread );La fonction incrémente le compteur de mise en sommeil et retourne la valeur du compteur.
• Pour redémarrer un threadDWORD ResumeThread( HANDLE hThread );La fonction décrémente le compteur de mise en sommeil et retourne la valeur du compteur.
jc/md/lp-01/06 Threads 10
Fin d’un thread• Pour terminer proprement un thread, le mieux
est d’utiliser la fonction ExitThread VOID ExitThread(DWORD dwExitCode);• Le code de sortie est récupérable par celui qui a
créé le thread par la fonction :BOOL GetExitCodeThread(
HANDLE hThread,
LPDWORD lpExitCode);
• L’appelant devra ensuite fermer le handle
jc/md/lp-01/06 Threads 11
Application THREAD1
• L’application va créer un thread qui sera suspendu par la fonction Sleep
• La durée de la suspension est fixée par le paramètre fourni par CreateThread
• On vérifiera– Que le thread est actif en testant le code de retour
259 en décimal– Puis qu’il se termine en renvoyant un code de sortie
différent, par exemple 12345678
• Enfin, CloseHandle ferme le handle
jc/md/lp-01/06 Threads 12
Génération de l’application
• Fonction main THREAD1.cpp– Ouverture du fichier– Insertion du code de main
• Fonction A_MAIN– Insertion d’un nouveau fichier THREAD1fonc.cpp
dans le projet– Ouverture du fichier– Insertion du code de la fonction
• Compilation des fichiers .cpp• Génération de l’exécutable .exe
jc/md/lp-01/06 Threads 13
Ouverture de THREAD1.cpp
Onglet FileView
jc/md/lp-01/06 Threads 14
THREAD1 main (1)
#include "stdafx.h "#define ATTENTE 1000void WINAPI A_MAIN(LPDWORD p); //déclaration fonctionint WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){
HANDLE hFils;DWORD argument_pour_le_fils; //pour l’exempleDWORD thread_fils_Id=0;LPDWORD lpThreadFilsId=&thread_fils_Id;DWORD code_mis_par_le_fils;
jc/md/lp-01/06 Threads 15
THREAD1 main (2)
printf("WinMain: début du thread primaire de THREAD1\n");
argument_pour_le_fils=ATTENTE //en ms
//Création du thread fils
hFils=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)A_MAIN,&argument_pour_le_fils,0,lpThreadFilsId);
jc/md/lp-01/06 Threads 16
THREAD1 main (3)
do //boucle d’attente de la fin du thread fils
{GetExitCodeThread(hFils,&code_mis_par_le_fils); //code actualisé à chaque passage
printf("WinMain: code de retour du thread fils: %d\n",code_mis_par_le_fils);
Sleep(400); //on redonne la main au système
}
while(code_mis_par_le_fils == STILL_ACTIVE);
jc/md/lp-01/06 Threads 17
THREAD1 main (4)
printf("WinMain: fin de la boucle d'attente\n");printf("WinMain: code de retour du thread fils :
%d\n",code_mis_par_le_fils);CloseHandle(hFils);printf("WinMain: fin du thread primaire (main de THREAD1)\n");getchar(); //attente d'un caractère pour
maintenir la fenêtre ouvertereturn 0;
}
jc/md/lp-01/06 Threads 18
Insertion d’un fichier dans le projet
jc/md/lp-01/06 Threads 19
Type et nom du fichier inséré
jc/md/lp-01/06 Threads 20
Ouverture du nouveau fichier
jc/md/lp-01/06 Threads 21
Insertion du code de A_MAIN
// THREAD1fonc.cpp #include "stdafx.h" //indispensable avec l'option /Yu du compilateur
void WINAPI A_MAIN(LPDWORD pAdresse_argument){
DWORD attente; //utilisée pour une meilleure clartéprintf("A_MAIN: début du thread fils\n");attente=*pAdresse_argument; //récupération de l’argumentprintf("A_MAIN: argument envoyé par WinMain= %d\n",attente);Sleep(attente);printf("A_MAIN: fin du thread fils après attente de %d
ms.\n",attente);ExitThread(12345678); //valeur arbitraire
}
jc/md/lp-01/06 Threads 22
Insertion d’un fichier existant
jc/md/lp-01/06 Threads 23
Chemin d’accès au fichier
jc/md/lp-01/06 Threads 24
Après insertion du code
jc/md/lp-01/06 Threads 25
Génération de THREAD1.exe
Build THREAD1.exe
jc/md/lp-01/06 Threads 26
Exécution de THREAD1
• Vérifier la connexion et télécharger l’image– Target→Configure Remote Connexion…– Target→Download/Initialize
• Choisir et exécuter THREAD1– Target→Run Program
Dans la boîte choisir Run Program choisir THREAD1.exe ou renseigner la zone Execution command line
– Cliquer le bouton Run
jc/md/lp-01/06 Threads 27
Résultat de l’exécution
jc/md/lp-01/06 Threads 28
Application THREAD2
• Accès aux identificateurs de threads et aux handles par GetCurrentThreadId et GetCurrentThread
– ThreadId du thread courant– ThreadId du père– ThreadId du fils
• SuspendThread• ResumeThread
jc/md/lp-01/06 Threads 29
Application THREAD2 : Main
• Récupération du ThreadId• Création d’un pseudo-handle personnel• Création du thread fils• Impression des valeurs• Réveil du thread fils après attente• Lectures des codes de retour du fils• Fermeture du handle fils• Retour au système
jc/md/lp-01/06 Threads 30
THREAD2 main (1)
// THREAD2.cpp //Defines the entry point for the appli.#include "stdafx.h" //obligatoire avec l'option de compil. /Yu#define ATTENTE 1000 //durée de l'attente
void WINAPI A_MAIN (LPDWORD pAdresse_argument);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
jc/md/lp-01/06 Threads 31
THREAD2 main (2)
{
HANDLE hFils;
HANDLE hPere;
DWORD threadId_pere=0;
DWORD threadId_fils=0;
LPDWORD lpThreadFilsId=&threadId_fils;
DWORD code_mis_par_le_fils;
jc/md/lp-01/06 Threads 32
THREAD2 main (3)
printf("WinMain: début du thread primaire de THREAD2\n");
hFils=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)A_MAIN,NULL,0,lpThreadFilsId);
hPere=GetCurrentThread();threadId_pere=GetCurrentThreadId();printf("WinMain: handle_pere= %d handle_fils=
%d\n",hPere,hFils);printf("WinMain: threadId_pere= %d threadId_fils= %d\
n",threadId_pere,threadId_fils);Sleep(ATTENTE);ResumeThread(hFils);
jc/md/lp-01/06 Threads 33
THREAD2 main (4)
GetExitCodeThread(hFils,&code_mis_par_le_fils);printf("WinMain: code de retour du thread fils : %d\
n",code_mis_par_le_fils);Sleep(ATTENTE);GetExitCodeThread(hFils,&code_mis_par_le_fils);printf("WinMain: code de retour du thread fils : %d\
n",code_mis_par_le_fils);CloseHandle(hFils);printf("WinMain: fin du thread primaire (main de
THREAD2)\n");getchar(); //attente d'un caractère pour…return (0);}
jc/md/lp-01/06 Threads 34
THREAD2 fonction
#include "stdafx.h" //indispensable avec l'option /Yu…void WINAPI A_MAIN(LPDWORD pAdresse_argument){
DWORD threadId=0;HANDLE hLocal;hLocal=GetCurrentThread(); //crée un pseudo-handlethreadId=GetCurrentThreadId();printf("A_Main: threadId= %d hLocal= %d\n",threadId,hLocal);SuspendThread(hLocal);ExitThread(87654321);
}
jc/md/lp-01/06 Threads 35
Mettre THREAD2 dans le noyau
jc/md/lp-01/06 Threads 36
MAKE IMAGE
jc/md/lp-01/06 Threads 37
Démarrer->Exécuter
jc/md/lp-01/06 Threads 38
Parcourir
jc/md/lp-01/06 Threads 39
Sélectionner THREAD2
jc/md/lp-01/06 Threads 40
OK
jc/md/lp-01/06 Threads 41
Résultat de l’exécution
jc/md/lp-01/06 Threads 42
Application THREAD3
• Dans une nouvelle application, THREAD3, nous allons remplacer dans TRHEAD2 le paramètre ATTENTE par une valeur lue sur la ligne de commande.
• Suppression du #define ATTENTE• Remplacement des deux occurrences de ATTENTE par
l’appel à la fonction _wtoi() qui convertit la chaîne UNICODE donnée sur la ligne d’attente en un entier
• Nous supposerons que le paramètre fourni sur la ligne de commande est saisi correctement, car le but est de montrer l’accès à la ligne de commande et non de tester les chaînes proposées, soit par exemple 1000 ou 12345
• On peut imprimer la valeur lue par un printf
jc/md/lp-01/06 Threads 43
THREAD3 main (1)
• Supprimer– #define ATTENTE 1000
• Remplacer les deux occurrences de– Sleep(ATTENTE); par– Sleep(_wtoi(lpCmdLine);
• THREAD3fonc identique à THRED2fonc• Générer la nouvelle image puis exécuter en
renseignant la boîte d’exécution avec le nom du programme suivi de 12345
jc/md/lp-01/06 Threads 44
Résultat de l’exécution
jc/md/lp-01/06 Threads 45
Conclusion
• Nous appris à créer des threads et à organiser les communications élémentaires entre un thread père et un thread fils