Timer zählt zu langsam

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
l0lhaxx
Beiträge: 89
Registriert: Di 8. Dez 2015, 09:20

Timer zählt zu langsam

Beitrag von l0lhaxx »

Hallo zusammen,
habe mir letztens ein kleines Programm mit mehreren Timern gebastelt. Das Programm funktioniert soweit, aber jetzt ist mir aufgefallen das der Timer (zählt von 24h abwärts) zu langsam zählt. Bei 3 Minuten macht das ca. 1-2 Sekunden Differenz aus. Weshalb? Ist das Programm mit den vielen Timern überfordert?

Hab es mal Angehängt.

Danke im voraus!
Zuletzt geändert von l0lhaxx am Do 4. Feb 2016, 13:25, insgesamt 1-mal geändert.

baumina
Beiträge: 152
Registriert: Mo 3. Feb 2014, 14:07
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Timer zählt zu langsam

Beitrag von baumina »

Ein Timer zählt nur wenn er Rechnerzeit bekommt. Du kannst also einen Timer nicht für eine korrekte Uhrzeit benutzen. Die aktuelle Uhrzeit bekommst du mit der Funktion now.
.

Mathias
Beiträge: 6919
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Timer zählt zu langsam

Beitrag von Mathias »

@l0lhaxx

So wie ich sehe, macht du 16x das gleiche,
Wieso packst du das ganze nicht eine eine Procedure ?
Ist doch einfacher als 16 mal Copy/Paste, vor allem wen du etwas ändern willst, zB. dein fehlerhafter Timer, dann muss du die 16x tun. :wink:

So wie ich es sehe brauchst du auch nur einen Timer, anstelle von 16 Stück.

Die Label-Ausgabe geht auch viel einfacher:

Code: Alles auswählen

  HH := HH + ':';
  MM := MM + ':';
  Label63.Caption := SS;
  Label62.Caption := MM;
  Label61.Caption := HH;
 
// einfacher so_
Labelxx.Caption:= HH + ':' + MM + ':' + SS
 
// oder direkt:
Labelxx.Caption:=Format('%.2d:%.2d:%.2d',[intHH, intMM, intSS]);
 
So kannst am einfachten die Zeit ausgeben, zeit ist der Start des Ablaufes (zeit := now).

Code: Alles auswählen

var
  zeit: TDateTime;
begin
  Label1.Caption := TimeToStr(now - zeit);
end;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Re: Timer zählt zu langsam

Beitrag von Christian »

TTimer ist nichts genaues. Er garantiert dir eigentlich nur das er mindestens Interval ms später aufgerufen wird. Wenn dein Programm oder das ganze System gerade ausgelastet ist wird er später aufgerufen. Das ganze passiert über die Message Que des Programms.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Timer zählt zu langsam

Beitrag von mse »

Christian hat geschrieben:TTimer ist nichts genaues. Er garantiert dir eigentlich nur das er mindestens Interval ms später aufgerufen wird.
Das müsste aber nicht so sein. Der Durchschnitt der Intervallzeit des MSEgui ttimer ist Mikrosekunden genau. Auf einem Linux System mit moderater Auslastung liegt auch der Jitter im Mikrosekundenbereich. Auf Windows ist der Jitter meist kleiner +-1ms wenn "options to_highres" gesetzt wird.
Realisiert wird dies indem sich das MSEgui Timersystem an der Realtimeclock orientiert und die einzelnen Zeitscheiben entsprechend anpasst.

l0lhaxx
Beiträge: 89
Registriert: Di 8. Dez 2015, 09:20

Re: Timer zählt zu langsam

Beitrag von l0lhaxx »

Mathias hat geschrieben: So wie ich es sehe brauchst du auch nur einen Timer, anstelle von 16 Stück.
Und wie soll das funktionieren? Teilweise laufen alle 16 Countdownzeiten gleichzeitig.
Mathias hat geschrieben: So kannst am einfachten die Zeit ausgeben, zeit ist der Start des Ablaufes (zeit := now).

Code: Alles auswählen

 
var
zeit: TDateTime;
begin
  Label1.Caption := TimeToStr(now - zeit);
end;
Tut mir leid aber ich versteh nicht ganz wie das funktionieren soll?!
mse hat geschrieben: Der Durchschnitt der Intervallzeit des MSEgui ttimer ist Mikrosekunden genau. AufAuf Windows ist der Jitter meist kleiner +-1ms wenn "options to_highres" gesetzt wird.
Und wie kann ich jetzt darauf zurückgreifen?

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Timer zählt zu langsam

Beitrag von mse »

l0lhaxx hat geschrieben:Und wie kann ich jetzt darauf zurückgreifen?
Das Verfahren in Lazarus zu integrieren ist vermutlich ziemlich anspruchsvoll. Der Code ist hier:
https://gitlab.com/mseide-msegui/mseide ... etimer.pas
Oder du verwendest MSEide+MSEgui.

SoE
Beiträge: 84
Registriert: Mo 31. Aug 2015, 01:51

Re: Timer zählt zu langsam

Beitrag von SoE »

Es gibt doch auch unter Windows noch einige Möglichkeiten:

Statt der SetTimer Function einen Multimedia Timer nehmen.
Zu XP Zeiten (mmSYSTEM) gab es doch:
timeGetDevCaps, timeBeginPeriod, EndPeriod
timeSetEvent, timeKillEvent
Höhere Windows Versionen haben da doch sicher auch was anzubieten!?

Ansonsten vielleicht ein eigener Thread + Sleep oder SleepEX
oder WaitableTimerAPI
oder QueueTimers (CreateTimerQueueTimer)
oder QueryPerformance Counter, QueryPerformanceFrequency
oder ab Windows 8: GetSystemTimePreciseAsFileTime

Vielleicht kann man damit ja was brauchbares bauen...

l0lhaxx
Beiträge: 89
Registriert: Di 8. Dez 2015, 09:20

Re: Timer zählt zu langsam

Beitrag von l0lhaxx »

Welche ist die schnellere Variante und gibt es irgendwo eine Anleitung dazu?

Mathias
Beiträge: 6919
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Timer zählt zu langsam

Beitrag von Mathias »

Und wie soll das funktionieren? Teilweise laufen alle 16 Countdownzeiten gleichzeitig.
Dies sollte als Gedankenstütze reichen:

Code: Alles auswählen

type
  TMyTimer = record
    start: TDateTime;
    aktiv: boolean;
  end;
 
var
  MyTimer: array[0..1] of TMyTimer;
 
{ TForm1 }
 
procedure TForm1.FormCreate(Sender: TObject);
var
  i: integer;
begin
  Button1.Caption := 'Start M1';  // Kann im Obj-Inspector gemacht werden
  Button2.Caption := 'Start M2';
  Button3.Caption := 'Reset M1';
  Button4.Caption := 'Reset M2';
  for i := 0 to Length(MyTimer) - 1 do begin
    MyTimer[i].aktiv := False;
  end;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  MyTimer[0].aktiv := True;
  MyTimer[0].start := Now;
end;
 
procedure TForm1.Button3Click(Sender: TObject);
begin
  MyTimer[1].aktiv := True;
  MyTimer[1].start := Now;
end;
 
procedure TForm1.Button2Click(Sender: TObject);
begin
  MyTimer[0].aktiv := False;
end;
 
procedure TForm1.Button4Click(Sender: TObject);
begin
  MyTimer[1].aktiv := False;
end;
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if MyTimer[0].aktiv then begin
    Label1.Caption := TimeToStr(Now - MyTimer[0].start);
  end else begin
    Label1.Caption := '-';
  end;
  if MyTimer[1].aktiv then begin
    Label2.Caption := TimeToStr(Now - MyTimer[1].start);
  end else begin
    Label2.Caption := '-';
  end;
end;     
Wen du es ganz elegant lösen willst, dann würde ich die Buttons und Label in Array packen und manuell im FormCreate erzeugen.
Das Klick-Ereignis brauchst du auch nur einmal, welcher Button das gedrückt wurde, kannst mit TButton(Sender).Tag abfragen.

Tönt schlimmer als es ist, dafür muss du nicht alles 16x kopieren.

Der Vorteil, wen zB. das Label eine andere Farbe oder Schrift braucht, dann muss es nur 1x geänder werden.

Ich hoffe ich kann dir helfen damit. :wink:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten