[THREAD] EXEMPLE DE "TIMER MICROSECONDE PAS TRÉS PRECIS"

f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 - 14 févr. 2006 à 06:43
 Utilisateur anonyme - 24 oct. 2007 à 22:55
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/36036-thread-exemple-de-timer-microseconde-pas-tres-precis

Utilisateur anonyme
24 oct. 2007 à 22:55
SALUT MES AMIS: j'ai un probleme avec le timer de Delphi je voudrer ajouter une parametre dans timer et j'arrive pas a ajouter alors aider moi svp, mon problem c'est a chaque fois on clic sur la form un nouveau boutton doit etre creer et la valaur 100 est affecter au caption de ce button j'usqua se mement c'est simple mais le probleme qui se pose: j'ai associe a chaque button une timer qui creer de meme principe de button maintenat je voudrer décrementer la valeur de chaque button indepondament au autres button jusqu'a arrivé a 0. merci d'avance et j'attend votre reponse.
cs_karim18 Messages postés 3 Date d'inscription dimanche 5 mars 2006 Statut Membre Dernière intervention 18 juin 2006
18 juin 2006 à 02:34
ce programme n'existe pas ??????????????
jlen100 Messages postés 1606 Date d'inscription samedi 10 juillet 2004 Statut Membre Dernière intervention 25 juillet 2014 13
23 févr. 2006 à 07:45
ACHP132--> à condition de pas travailler sous XP puisque dans ce cas il n'y a pas de dos mais seulement une émulation du dos gérer par Windows et il reprend la main régulièrement pour traiter les messages.
Comme tu travailles en temps partagé tu ne garantiras pas la durée du traitement (ni à la milliseconde et encore moins à la microseconde)
ACHPI32 Messages postés 50 Date d'inscription mercredi 2 avril 2003 Statut Membre Dernière intervention 9 mai 2009
23 févr. 2006 à 01:15
y'a pu qu'a sortir le free pascal ou le TP7 et faire un programme sous DOS... lol
jlen100 Messages postés 1606 Date d'inscription samedi 10 juillet 2004 Statut Membre Dernière intervention 25 juillet 2014 13
17 févr. 2006 à 23:44
pour éviter l'appel a application.ProcessMessage il faudrait passer par une gestion évènementielle (comme le fait le timer) et ne gérer que l'évènement. Mais même dans ce cas la précision n'est pas garantie en effet Windows place l'évènement dans une file de traitement et il ne sera traité que lorsque les précédents auont été traité. La réaction est meilleure que le traitement du thread seul mais il n'est pas "en temps réel" mais en batch (par exemple si un évènement comme un ontimer est en court de traitement l'évenement ne sera traité qu'après et cela peut prendre des millisecondes) l'avantage est que le thread continue d'être traité et qu'on ne cumule pas les erreurs, enfin dans la limite de charge du processeur. Comme il n'y a qu'un seul processeur il faut bien qu'il traite toutes les demandes!
On rencontre d'ailleurs le même problème quand on gère des interruptions: on donne des priorités mais il y a toujours des taches favorisées et d'autres qui attendent; quand on travaille en assembleur et qu'il n'y a pas trop de processus en cours on arrive à s'en sortir mais dans le cas de window s'est pratiquement impossible (le nombre et la priorité des processus peut varier)
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
17 févr. 2006 à 23:04
tu sais de ou viens ton probleme ?

je vais te le dire : l'appel de Application.ProcessMessage dans ton thread.

mais si on l'enleve, l'application freeze ... normal.
jlen100 Messages postés 1606 Date d'inscription samedi 10 juillet 2004 Statut Membre Dernière intervention 25 juillet 2014 13
15 févr. 2006 à 15:50
non laisses la elle est un exemple d'ulisation de thread par contre il vaudrait peut être mieux la renommer et mettre un avertissement

@+
jlen
Sylvainlefou Messages postés 43 Date d'inscription vendredi 27 décembre 2002 Statut Membre Dernière intervention 15 février 2006
15 févr. 2006 à 15:37
Ok, vous confirmez ce que je pensais, mon timer est nul et useless, lol, tempi ! :) :)
Je vire la source où peut-elle servir ?
jlen100 Messages postés 1606 Date d'inscription samedi 10 juillet 2004 Statut Membre Dernière intervention 25 juillet 2014 13
15 févr. 2006 à 15:25
oui kenavo le MMTimer il est très précis mais assez gourmand en ressource.
de toute façon dés que tu mets un application.processmessage le taux d'occupation passe à 100% en effet windows reboucle sur l'instruction while tant que la condition de sortie n'est pas remplie; mais cela n'a pas d'influence sur le déroulement des autres programes puisqu'il ne revient dans le while q'après avoir traité les messages et autres threads cela permet simplement une réponse plus rapide qu'un scan et sans bloquer Windows le probléme restant c'est qu'on ne peut pas déterminer à l'avance combien durera une boucle puisqu'elle dépend du nombre et de la priorité des thread et des messages et que par conséquent cette durée est tout à fait aléatoire (ce qui est d'ailleurs à l'origine du manque de précision de ce timer.

@+
jlen
cs_Kenavo Messages postés 702 Date d'inscription vendredi 21 mars 2003 Statut Membre Dernière intervention 1 octobre 2009 5
15 févr. 2006 à 14:52
Arghhhh .....
"If FEnabled=True then Main; "
"until FEnabled = False;"
Ben non ! Ecris plutôt :
"If FEnabled then Main; "
"until not FEnabled;"

Sinon pour le timer, c'est une catastrophe ! Je déconseille aux âmes sensibles d'aller voir le taux d'occupation du processeur !
Le meilleur timer est .... le timer le mieux adapté au problème !
Rylryl l'utilisait pour séquencer des trames de télécommande RC5 (durée de la trame 25 ms, duré du bit 1,78 ms) où il était adapté : Besoin de précision et utilisation courte. Pour des périodes de l'ordre de la seconde, le timer TTimer est très correct. Entre 1 et 100 millisecondes, le timer multimedia est sans doute le plus adapté.

Kenavo
jlen100 Messages postés 1606 Date d'inscription samedi 10 juillet 2004 Statut Membre Dernière intervention 25 juillet 2014 13
14 févr. 2006 à 18:31
retour sur le pc principal
jlen100 Messages postés 1606 Date d'inscription samedi 10 juillet 2004 Statut Membre Dernière intervention 25 juillet 2014 13
14 févr. 2006 à 18:27
test à partir d'un autr PC
Sylvainlefou Messages postés 43 Date d'inscription vendredi 27 décembre 2002 Statut Membre Dernière intervention 15 février 2006
14 févr. 2006 à 15:40
Le petit exemple d'utilisation du timer a était codé simplement pour montrer l'irrégularité du timer, il est vrai qu'ils n'est pas trés propre.

f0xi : merci, c'est vrai qu'un while...do semble plus logique qu'un repeat...until, je ne met pas a jour la source mais je modifie mon code.
Sinon la liste servait a montrer que, chaque seconde, il y avant un décalage de x milliseconde. cependant, un label reste beaucoup plus léger pour la machine (méme si les temps d'executions de "OnTimer" sont compensée).

pepitto : cette gestion des timers est la maniere plus direct, d'utiliser les timers windows (API). C'est ca qui est utiliser par le composant TTimer.

jlen100: il faut alors géré, en plus du temps d'execution de "OnTimer", les temps de Application.ProcessMessages et des differentes boucles, de la creation du thread... il y a pas mal de choses a changer, je vais voir cela.

Merci a tous
Sylvainlefou Messages postés 43 Date d'inscription vendredi 27 décembre 2002 Statut Membre Dernière intervention 15 février 2006
14 févr. 2006 à 14:58
Message envoyé par jlen100 :
"salut,pas mal ton code. Une petite chose tu n'as pas donné de priorité à la construction (si je ne trompe pas par défaut elle doit être à Priority := tpNormal)
pour les décalages j'ai eu le même probleme avec un thread et ce quelque soit la priorité donnée; le decalage pouvant atteindre 15ms en fait cela s'explique facilement : avec le Application.processmessages on indique au programme qu'il doit redonner la main à windows qui gère la file d'attente (et celà est préférable sous peine de blocage) résultat il faut bien qu'il traite aussi les autres threads et cela prend comme le refroidissement du fût du canon ... un certain temps.
en conclusion il est pratiquement impossible de garantir un timming précis en dessous de la milliseconde sans bloquer le processus (interdire à windows de traiter les threads).
Pour obtenir des timming plus petit il faut passer par des cartes d'extension qui génèrent le signal (avec ou sans bufferisation des données s'il faut les transmettre) une carte à microcontroleur fait génèralement l'affaire avec des horloge à 20 ou 50MHz on arrive facilement à des signaux precis à 50 à 100ns
Mais la persistance rétienienne étant ~100ms un timer standard réglé à 40/50 ms fait très bien l'affaire tu peux même descendre à 20ms en gardant un bonne reproductivité. Mais comme je ne connais pas ton application je ne fairais pas plus de commentaires"
j'espère que cela pourra t'être utile

@+
jlen
cs_pepitto Messages postés 22 Date d'inscription jeudi 13 novembre 2003 Statut Membre Dernière intervention 25 juin 2008
14 févr. 2006 à 13:34
Si tu n'est pas à la seconde je te propose d'utiliser une petite fonction simple (tu peux trouver l'aide dans Win32.hlp) qui utilise les messages :

dans private ajoute :
procedure OnTimer(var msg : Tmessage); message WM_TIMER;

//--------------------------------------------

procedure TForm1.OnTimer(var msg : Tmessage);
begin
// ici places les action à effecturer toutes les secondes
if Msg.wParam = 1234 then // si plusieurs timers une sellection
// est possible avec wParam
begin


end;
end;

//-------------------------------------------------
dans Procedure Tform1.Create(Sender: TObject); ajoute
setTimer(Handle,
1234, // identifiant du timer
1000, // temps en milliseconde (1 seconde dans ce cas)
nil); // voir aide (je ne suis pas trop copain avec l'anglais)


// pour stopper le timer utilies
Killtimer(Handle,
1234); //identifiant du timer


Toutes ces lignes peuvent t'éviter de creer un timer est peut être très simple d'utilisation (Quand on essaie l'emploie les <<message>>)
Utilisateur anonyme
14 févr. 2006 à 12:01
Salut,
Wolf ce qui est valable pour toi ne l'est pas forcément pour les autres.
Si aujourd'hui tu ne vois aucune utilité à un timer de haute précision, demain il en sera peut être autrement. C'est sur que pour afficher un message où fermer un rideau c'est pas utile d'être précis à la microseconde mais il n'y a pas que ça, je pense notamment au multimédia qui dans certaine circonstance demande une précision extrême mais il y a encore plein d'autres applications.

@+
Cirec
wolf691300 Messages postés 41 Date d'inscription mardi 15 juin 2004 Statut Membre Dernière intervention 31 mars 2006
14 févr. 2006 à 09:12
Je ne suis pas à une seconde près pour créer une application. Tant que l'exécutable fonctionne bien avec un Timer normal ... J'en vois aucune utilité d'amélioration, idem dans le monde réel.

Wolf691300
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
14 févr. 2006 à 06:43
modification dans Create :

procedure TForm1.FormCreate(Sender: TObject);
begin
LongTimeFormat := 'hh:nn:ss.zzz';
MicroTimer1 := MicroTimer.Create(nil);
MicroTimer1.OnTimer := MicroTimer1OnTimer;
end;
__________________________________________________________________

modification de OnTimer :

procedure TForm1.MicroTimer1OnTimer(Sender: TComponent);
var t : int64;
begin
QueryPerformanceCounter(t);
caption := format('%s || %d',[TimeToStr(now),t]);
end;
__________________________________________________________________

modification de Main() :

Procedure MicroTimer.Main();
var
Time_now, Time_memo, IntervalRecalc: Int64;
Ic : integer;
begin
Time_now := 0;
Time_memo := 0;
Ic := 0;
while FEnabled do begin
IntervalRecalc := FInterval - (Time_now - Time_memo) * 1000000 div FFrq_Base;
FThread:= MicroTimerTh.Create(FFrq_Base, IntervalRecalc);
while (not(FThread.ThreadTerminated)) and (FEnabled) do
if Ic = 1000 then begin
Application.ProcessMessages;
Ic := 0;
end;
Inc(Ic);
end;
QueryPerformanceCounter(Time_memo);
FOnTimer(Self);
QueryPerformanceCounter(Time_now);
end;
end;
__________________________________________________________________

Modification d'execute :

procedure MicroTimerTh.Execute;
var
Time_memo, Time_now, dif: Int64;
begin
QueryPerformanceCounter(Time_memo);
while dif <= FInterval do begin
QueryPerformanceCounter(Time_now);
dif := (Time_now - Time_memo) * 1000000 div FFrq_Base;
end;
end;
__________________________________________________________________

evite de balancer des données qui change tout le temps dans une liste ... utilise un label plutot ou un tstringlist (durant le calcul).