Академический Документы
Профессиональный Документы
Культура Документы
Support de formation
1.1
La notion de "handle"
Nous avons bien compris que l'essentiel de notre travail se fait sur les classes qui comportent l'ensemble des dfinitions des proprits et des mthodes. Une classe peut gnrer des objets au cours d'une opration de cration. Lorsque l'objet est cr, la mthode de cration rserve la mmoire ncessaire pour "loger" l'objet. Pour manipuler l'objet, il faut connatre son adresse: c'est le rle des "Handle" ou poignes (16384 max.) qui sont des pointeurs contenant l'adresse de celui-ci. Ces pointeurs sont utiles pour manipuler tous types d'objets Windows: visuels: fentres, barres d'outils et de menus, boutons, listes, graphiques (GDI): bitmaps, stylos, brosses, systmes (kernel): processus et traitements, communications, fichiers,
page 2/14
1.2
Puisque nous utilisons les fonctions du GDI, il nous faut une poigne supplmentaire (de type HDC), appele contexte de dispositif. En effet, ceci permet d'indiquer au systme o nous allons dessiner (cran, imprimante, ).
page 3/14
2.
2.1
MULTITRAITEMENT
Le problme du systme multitches
Windows est un systme d'exploitation multitches, c'est dire que plusieurs programmes (tches) peuvent tre excutes simultanment. Pourtant, ce systme d'exploitation n'est pas premptif , c'est dire qu'une application peut mobiliser le processeur temps complet. Il est donc indispensable d'ajouter des lignes de code dans nos applications pour viter ce phnomne, particulirement embarrassant dans l'excution des boucles (ex: Application.ProcessMessages). Chaque fois que nous excutons une application standard, une tche est cre. Windows rserve une zone de mmoire (4Go. virtuels) pour ses besoins. D'autre part la tche va excuter un traitement nomm "Thread": c'est le traitement principal de l'application. Lors de l'excution active du traitement, il est souvent difficile de lancer une autre action ou mme de dplacer la fentre d'excution. Essayez le code suivant dans une fiche pourvue d'un "Edit" et d'un "Button": procedure TForm1.Button1Click(Sender: TObject); var i:integer; begin for i:=1 to 100000 do Edit1.Text:=IntToStr(i); end; On ne voit mme pas l'affichage dfiler, puisque les messages envoys au composant "Edit" ne sont pas traits pendant l'excution de la boucle. Le fait de rajouter une ligne de code amliore la situation, on peut mme dplacer la fentre. procedure TForm1.Button1Click(Sender: TObject); var i:integer; begin for i:=1 to 10000 do begin Edit1.Text:=IntToStr(i); Application.ProcessMessages; end; end;
page 4/14
Je souhaite voir dfiler 2 compteurs en mme temps. Je rajoute donc un 2 "Edit" et un 2 "Button" auquel j'affecte une procdure semblable: procedure TForm1.Button2Click(Sender: TObject); var j:integer; begin for j:=1 to 10000 do begin Edit2.Text:=IntToStr(j); Application.ProcessMessages; end; end; A l'excution, je constate que le fait d'appuyer sur le premier bouton fait bien dfiler le 1er compteur. Pendant ce temps, j'appuie sur le 2 bouton: le premier compteur est suspendu alors que le 2 fonctionne. Ds son arrt, le 1er termine son travail. Il est maintenant vident qu'un programme habituel n'accomplit qu'un seul traitement. Les diffrentes procdures sont empiles puis dpiles par le systme, mais ne peuvent "tourner" simultanment. L'alternative cette problmatique est la cration de traitements (Threads) " la vole", on va faire croire l'utilisateur qu'il dispose de plusieurs processeurs (16 max).
page 5/14
A. On peut commencer crire la procdure excuter par le traitement: procedure MonTraitement; var i:integer; begin i:=0; while true do begin inc(i); Form1.Edit1.Text:=format('Le compteur : %d',[i]); end; end; N'ayons pas peur ici d'une boucle infinie, puisque le traitement peut tre interrompu par une commande particulire. B. Dclarer les variables ncessaires au traitement (en global pour l'unit): var ThreadID, hThread: THandle; Un traitement est caractris par 2 proprits, son numro et le pointeur servant le manipuler. Rappel: un "handle" est un pointeur permettant de manipuler les objets de Windows dans le cas de l'utilisation des mthodes des APIs.
page 6/14
C. Ecrire la procdure pour le bouton "Marche1" procedure TForm1.BtM1Click(Sender: TObject); begin HThread:=CreateThread(nil,0,@MonTraitement,nil,0,ThreadID); end; Nous faisons appel ici la fonction "CreateThread" de l'API Windows ( vois dans l'aide en ligne). D. Ecrire la procdure pour le bouton "Suspend 1" procedure TForm1.BtS1Click(Sender: TObject); begin SuspendThread(HThread); end; Un traitement peut "s'endormir" !!! E. Ecrire la procdure pour le bouton "Reprend 1" procedure TForm1.BtR1Click(Sender: TObject); begin ResumeThread(HThread); end; Un traitement peut "se rveiller" !!! F. Ecrire la procdure pour le bouton "Arrt 1" procedure TForm1.BtA1Click(Sender: TObject); begin TerminateThread(hThread,0); end; Un traitement peut heureusement s'arrter.
page 7/14
G. Vrifier le fonctionnement puis refaire de mme pour le 2 traitement. Le code complet sera voisin du suivant: unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) BtM1: TButton; Edit1: TEdit; BtA1: TButton; Edit2: TEdit; BtM2: TButton; BtA2: TButton; BtS1: TButton; BtS2: TButton; BtR1: TButton; BtR2: TButton; procedure BtM1Click(Sender: TObject); procedure BtA1Click(Sender: TObject); procedure BtM2Click(Sender: TObject); procedure BtA2Click(Sender: TObject); procedure BtS1Click(Sender: TObject); procedure BtS2Click(Sender: TObject); procedure BtR1Click(Sender: TObject); procedure BtR2Click(Sender: TObject); private { Dclarations prives} public { Dclarations publiques} end; var Form1: TForm1; ThreadID, hThread: THandle; ThreadID2, hThread2: THandle; implementation {$R *.DFM} procedure MonTraitement; var i:integer; begin i:=0; while true do
Maurice GINDENSPERGER (V 6.0)
page 8/14
begin inc(i); Form1.Edit1.Text:=format('Le compteur : %d',[i]); end; end; procedure MonTraitement2; //stdcall; var j:integer; begin j:=0; while true do begin inc(j); Form1.Edit2.Text:=format('Le compteur : %d',[j]); end; end; procedure TForm1.BtM1Click(Sender: TObject); begin HThread:=CreateThread(nil,0,@MonTraitement,nil,0,ThreadID); end; procedure TForm1.BtA1Click(Sender: TObject); begin TerminateThread(hThread,0); end; procedure TForm1.BtM2Click(Sender: TObject); begin HThread2:=CreateThread(nil,0,@MonTraitement2,nil,0,ThreadID2); end; procedure TForm1.BtA2Click(Sender: TObject); begin TerminateThread(hThread2,0); // ou mieux, utiliser la fonction ExitThread end; procedure TForm1.BtS1Click(Sender: TObject); begin SuspendThread(HThread); end; procedure TForm1.BtS2Click(Sender: TObject); begin SuspendThread(HThread2); end; procedure TForm1.BtR1Click(Sender: TObject); begin ResumeThread(HThread); end;
Maurice GINDENSPERGER (V 6.0)
page 9/14
procedure TForm1.BtR2Click(Sender: TObject); begin ResumeThread(HThread2); end; end. Le fonctionnement des traitements n'empche pas l'excution d'autres tches, ni le traitement des messages par l'application: on peut donc quitter celle-ci tout moment. D'autre part, on remarque que le traitement principal du programme n'est pas sollicit et que les 2 traitements s'excutent une vitesse voisine. Il est possible de changer la priorit des traitements.
2.3
Il est possible de changer la priorit des traitements par la fonction SetThreadPriority. Exemple pour notre bouton "Marche 1": procedure TForm1.BtM1Click(Sender: TObject); begin HThread:=CreateThread(nil,0,@MonTraitement,nil,0,ThreadID); SetThreadPriority(HThread,THREAD_PRIORITY_HIGHEST);// end; On constate maintenant que le premier compteur est plus rapide que le second. Le systme de priorit n'est pas simple, puisqu'il faut d'abord tenir compte de la classe de priorit de la tche (application). 2.3.1 Priorits des applications La fonction "GetPriorityClass" retourne la priorit de la tche. Priorit application HIGH_PRIORITY_CLASS IDLE_PRIORITY_CLASS NORMAL_PRIORITY_CLASS REALTIME_PRIORITY_CLASS Signification haute priorit: utilise presque toutes les ressources du processeur basse priorit: s'excute quand la charge du processeur est voisine de zro priorit normale priorit absolue: mme sur les disques et la souris Indice 13 4 79 24
page 10/14
2.3.2 Priorits des threads (traitements) La fonction GetThreadPriority nous renseigne sur la priorit en cours. Indicateur de priorit du traitement THREAD_PRIORITY_ABOVE_NORMAL THREAD_PRIORITY_BELOW_NORMAL THREAD_PRIORITY_HIGHEST THREAD_PRIORITY_IDLE THREAD_PRIORITY_LOWEST THREAD_PRIORITY_NORMAL THREAD_PRIORITY_TIME_CRITICAL Indice de priorit + 1 / tche - 1 / tche + 2 / tche valeur de 1 pour toutes les tches sauf REALTIME_PRIORITY_CLASS (16). - 2 / tche + 0 / tche valeur de 15 pour toutes les tches sauf REALTIME_PRIORITY_CLASS (31).
2.4
Temps d'excution
Attention, sous Windows, on ne sait jamais quel va tre le temps d'excution d'un traitement. Il n'est videmment plus question de chronomtrer, puisque plusieurs traitements s'effectuent "en parallle". 2.4.1 Suspendre l'excution d'une dure connue Employer la fonction Sleep(Millisecondes). 2.4.2 Attendre un vnement Utiliser la fonction WaitMessage Envoyer un message au traitement: PostThreadMessage
page 11/14
3.
3.1
Choisir "Fichier- Tout fermer" puis "Fichier - Nouveau - Autre" puis "Fiche active" dans l'onglet "Active X".
Taper le nom:
page 12/14
Enregistrer dans un nouveau dossier bien identifi. Choisir "Excuter - recenser le serveur Active X":
page 13/14
Choisir "Projet -dployer pour le Web". Si tout va bien, on doit obtenir une page WEB:
On constate le fonctionnement.
page 14/14