Delphi-PRAXiS
Seite 1 von 2  1 2   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   GetTickCount beeinflusst von PC Auslastung (https://www.delphipraxis.net/185380-gettickcount-beeinflusst-von-pc-auslastung.html)

MisterIXI 4. Jun 2015 19:38

GetTickCount beeinflusst von PC Auslastung
 
Hallo!

Ich habe heute im Prinzip eine Stoppuhr fertiggestellt, die ich für genaue zeitmessungen bräuchte.
Um genau zu sein würde ich sie benutzen um "Splits" beim Speedrunnen eines Spiels zu setzen. (wenn ihr nicht wisst, was es ist ist es auch nicht schlimm :wink: )

Auf jeden Fall soll die Zeitmessung sehr genau ablaufen, allerdings habe ich gemerkt das bei hoher CPU auslastung (die beim Streamen des Spiels der Fall ist) die Uhr manchmal flakert und auch langsamer läuft als ein profesionell gestalteter timer.

Mein code ist folgender:
Code:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Time:=Time+GetLocalTime-Tick;
Segment:=Segment+GetLocalTime-Tick;
Label1.Caption:=MSFormat(Time);
Tick:=GetLocalTime;
end;
Ja, ich weiß für die umbennenung war ich noch zu faul, die mach ich oft erst wenns es funktioniert ^^

"MSFormat" Formatiert nur die Zeit, in MS in das Format Min:Sek:Millisek, also sollte das eigentlich auch kein Problem darstellen.

Naja, ich habe es auch so verstanden dass der benannte "Tick" in Ms gemessene Zeit seit dem Start des Computers ist. Und meine Theorie: dass wenn der CPU überfordert wird irgendwas langsamer läuft.

Nach einem frischen Neustart ohne andere geöffnete Programme funktioniert soweit alles prima.
Sobald ich aber aufnahme/ das Streamen Starte habe ich z.T. bei 1 Minute bereits 2 Sekunden abweichung zu dem anderen Programm.


Irgendwelche Ideen? :pale:

Vielen Dank im Vorraus!

himitsu 4. Jun 2015 19:59

AW: GetTickCount beeinflusst von PC Auslastung
 
"sehr genau" und GetTickCount/TTimer/... wiedersprechen sich.
Alles unterhalb weniger Vielfacher von 16 ms kannst du vergessen.

Und ausßerdem bist du selber für die Ungenauigkeit verantwortlich.
Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
var
  Temp: TDateTime;
begin
  Temp := GetLocalTime;
  Time := Time + Temp - Tick;
  Segment := Segment + Temp - Tick;
  Label1.Caption := MSFormat(Time);
  Tick := Temp;
end;
Und wenn Time und/oder Tick auch nicht Fließkommazahlen sind, dann kommen schnell auch noch die Rundungsfehler dieser Typen dazu.


Delphi-Referenz durchsuchenTStopwatch
Multimedia-Timer
QueryPerformanceCounter
ASM RDTSC (Read Time Stamp Counter)
uvm.

hathor 4. Jun 2015 20:08

AW: GetTickCount beeinflusst von PC Auslastung
 
Wenn Du die CPU-Last wissen willst, dann zeige sie an:
Timer1.Interval:= 1000; // kürzer muss es nicht sein!

Delphi-Quellcode:
private
   Times: TThread.TSystemTimes;

procedure TForm1.FormCreate(Sender: TObject);
begin
TThread.GetSystemTimes(Times);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var Usage: Integer;
begin
  Usage := TThread.GetCPUUsage(Times);
  ProgressBar.Position := Usage; // Percent 0 - 100
end;

Popov 4. Jun 2015 20:39

AW: GetTickCount beeinflusst von PC Auslastung
 
Also die Zeit zu messen in dem man im Timer OnTimer Ereignis die Zeit, bzw. Ticks addiert ist leider ein unsinniges Unterfangen. Das Intervall ist nicht gleichmäßig. Stellt man das Intervall auf 100 ms, kann, wird aber eher nicht, das Ereignis 10 mal in der Sekunde aufgerufen werden. Somit bringt das nichts.

Besser ist den Zeitunterschied zu messen, z. B. so:
Delphi-Quellcode:
uses
  DateUtils;

var
  T1, T2: TTime;


procedure TForm1.FormCreate(Sender: TObject);
begin
  Timer1.Interval := 1;
  Timer1.Enabled := False;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  T1 := 0;
  T2 := 0;

  Timer1.Enabled := True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  MSBetween: Int64;
  TimeTemp: TTime;
begin
  if T1 = 0 then
    T1 := Time;

  T2 := Time;
  MSBetween := MilliSecondsBetween(T1, T2);
  TimeTemp := MSBetween / 24 / 60 / 60 / 1000;
  Label1.Caption := FormatDateTime('hh:nn:ss:zzz', TimeTemp);
end;
Beim Start wird die aktuelle Uhrzeit gemessen. Danach wird immer die Differenz zu der Startzeit gemessen. Da die Uhrzeit separat getaktet wird, sollte PC Auslastung keine Rolle spielen.

//EDIT:

Ich hab mir das Ganze mal angeguckt und da sind einige unnötige Zeilen. Der Code oben nur etwas kürzer:
Delphi-Quellcode:
uses
  DateUtils;

var
  T1: TTime;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Timer1.Interval := 1;
  Timer1.Enabled := False;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  T1 := 0;
  Timer1.Enabled := True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  TimeTemp: TTime;
begin
  if T1 = 0 then
    T1 := Time;

  TimeTemp := MilliSecondsBetween(T1, Time) / 24 / 60 / 60 / 1000;
  Label1.Caption := FormatDateTime('hh:nn:ss:zzz', TimeTemp);
end;

MisterIXI 4. Jun 2015 22:38

AW: GetTickCount beeinflusst von PC Auslastung
 
Vielen Dank für die schnellen Antworten!

(Und nochmal zur Anmerkung: meine Kenntnisse gehen kaum über ausgeweitete Grundkenntnisse hinaus, und ich bringe mir alles nach und nach anhand von Beispielen bei)

Zitat:

Delphi-Referenz durchsuchenTStopwatch
Multimedia-Timer
QueryPerformanceCounter
ASM RDTSC (Read Time Stamp Counter)
uvm.
Ich habe (das erste mal überhaupt) einen Multimedia Timer (den CKMultimediaTimer) als Komponente installiert. Allerdings weißt er dasselbe Problem auf, nur etwas weniger.

Also die Idee mit GetLocalTime hatte ich erst auch, aber da ich irgendwie nicht herausgefunden habe wie ich das zu benutzen habe, hatte ich es dann doch gelassen. Und jetzt als ich versucht habe das so zu benutzen, gibt mir Delphi immer den fehler "nicht genügent wirkliche Parameter" und was ich dann in die Klammer setzen soll finde ich irgendwie auch nicht heraus.
Was ich gefunden habe war [...] GetlocalTime(_Systemtime(now));
Ich bin mit mehr oder weniger ausprobieren an diesen Punkt gekommen. Aber egal ob ich nun now oder eine Zahl eingebe sagt mir Delphi: "ungültige Typunwandlung" :/


Und den Vorschlag von Popov versuche ich jetzt mal zu implementieren und zu verstehen. :oops:

Wenn das -warumauchimmer- auch nicht klappen sollte versuche ich wohl mal alles über die TStopwatch zu machen

Popov 4. Jun 2015 22:52

AW: GetTickCount beeinflusst von PC Auslastung
 
Es sollte klappen.

MisterIXI 4. Jun 2015 23:27

AW: GetTickCount beeinflusst von PC Auslastung
 
Auch wenn ich gerne sagen würde dass es geht, muss ich leider enttäuscht sagen, dass ich diese Version eines Timers zwar komplett verstehe, und auch keine Fehler bekomme , allerdings bleibt er immer auf 00:00:000 stehen.
Ich hasse es wenn es von der Logik gehen müsste, aber es einfach nicht geht :evil:

Ich gehe persönlich davon aus, dass bei mir "time" vielleicht nicht richtig abgegriffen wird?

Popov 4. Jun 2015 23:55

AW: GetTickCount beeinflusst von PC Auslastung
 
Der Timer1 ist nicht dazu da um etwas zu zählen, schon gar nicht Ticks, sondern nur um den aktuellen Stand in Label1.Caption anzuzeigen:
Delphi-Quellcode:
uses
  DateUtils; //Die Unit DateUtils wird für die Funktion MilliSecondsBetween benötigt

var
  T1: TTime; //Globale TTime Variable um die Startzeit zu merken

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Interval ist für die Zählung irrelevant.
  // Sagt nur aus wie oft die Anzeige aktualisiert wird.
  Timer1.Interval := 1;
  Timer1.Enabled := False; //Timer1 zuerst deaktivieren
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  // Es wird nicht ab 0 gezählt.
  // Die 0 ist nur dazu da um festzustellen ob T1 bereits einen Wert hat
  T1 := 0;
  Timer1.Enabled := True; // Stoppur starten
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  TimeTemp: TTime;
begin
  if T1 = 0 then // Wenn T1 = 0, dann ist es der ersten Durchlauf
    T1 := Time; // In dem Fall die Startzeit merken

  // Nun die Differenz (Int64) zwischen Startzeit und aktuellen Zeit vergleichen.
  // Bei TDateTime sind ganze Werte Daten, Nachkommawerte Zeiten.
  // Deshalb TimeTemp durch 24 Stunden, 60 Minuten, 60 Sekunden und 1000 Millisekunden teilen
  // Ergebnis ist eigentlich Zeit ab 00:00:00 Uhr
  TimeTemp := MilliSecondsBetween(T1, Time) / 24 / 60 / 60 / 1000;
  // Was angezeigt wird ist eigentlich die Uhrzeit, man merkt aber keinen Unterschied
  Label1.Caption := FormatDateTime('hh:nn:ss:zzz', TimeTemp);
end;

MisterIXI 5. Jun 2015 00:08

AW: GetTickCount beeinflusst von PC Auslastung
 
Okay auf die Idee hätte ich mal vorher kommen können: in einem neu geöffnetem Projekt funktioniert der Code. Allerdings in dem ganzen Konstrukt nicht <.<
Danke die kommentierte Version hat mir das ganze nocheinmal klar gemacht.
Ich versuche jetzt mal die Stelle zu finden an der es hakt indem ich systematisch auskommentiere.

MisterIXI 5. Jun 2015 00:41

AW: GetTickCount beeinflusst von PC Auslastung
 
Ok Ich habe meinen Fehler gefunden...
Ich hatte eine Variable vorher "Time" genannt, die immer durch den Zähler verändert wurde - logischerweise blieb es die ganze Zeit über auf Null.
Jetzt, da ich die Variable umbenannt habe, läuft der Timer ganz normal hoch.

Ich habe mein ganzes Programm inzwischen auch schon umgeschrieben, dass es mit den Werten auch rechnet und alles funktioniert

Vielen, vielen Dank für die Hilfe!! Das ist echt riesig! :thumb:


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:49 Uhr.
Seite 1 von 2  1 2   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz