![]() |
Ungenauigkeit von TDateTime / Alternative?
Hi,
Ich möchte gerne JEDE Sekunde eine Aktion ausführen und diese dann samt Ergebnis zu späteren Analyse Zwecken abspeichern. Dabei ist es mir wichtig, das ich auch wirklich für jede Sekunde ein Ergebnis erhalte. Deshalb hab ich meinen Timer, der sekündlich diese Aktion anstoßen soll, auch nicht einfach mit 1000ms getacktet, sondern mit 1ms. Und in jedem Durchlauf frage ich dann ab, ob seit der letzten Aktion schon eine Sekunde vergangen ist. Das heisst, wenn ich die Aktion ausfühe speichere ich unter FlastAction vom Typ TDatime das aktuelle Datum/Uhrzeit folgendermaßen:
Delphi-Quellcode:
Dann frage ich in jedem Timer Aufruf
Flastaction: TDateTime;
//... FLastAction:=Now;
Delphi-Quellcode:
Nun passierte es häufiger, dass ich dann beim Auswerten der Datensätze nur 59 Aktionen in der Minute hatte, d.h. iwie wurde einmal nichts ausgelöst. Und etwas rechenintensives, dass auch nur annäherend für 1 sec das Hauptprogramm blockieren würde ist nicht dabei.
if SecondsBetween(Now,FLastAction) > 0 then
//Stoße nächste Aktion an, speicher Now als FlastAction und als Startpunkt der Aktion Jetzt hab ich testweise etwas ganz blödes gemacht und statt secondsbetween folgendes benutzt:
Delphi-Quellcode:
und jetzt habe ich plötzlich durchgehend meine 60 Aktionen pro Minute.
if FormatDateTime('ss',Now)<>FormatDateTime('ss',FLastAction) then
//Stoße nächste Aktion an, speicher Now als FlastAction und als Startpunkt der Aktion Jetzt meine Fragen: - Ist das Zufall und wenn ich Pech hab verlier ich hin und wieder trotzdem mal ein paar Sekunden? - Gibt es vielleicht eine andere Möglichkeit jede Sekunde etwas auszuführen? Da es eigentlich nicht an zuviel Rechenaufwand für eine Sekunde liegen kann, würde mich da auch ein extra Thread nicht wirklich weiterbringen oder? :gruebel: |
Re: Ungenauigkeit von TDateTime / Alternative?
Mit nem Timer bekommste sowieso keine 1ms hin, da brauchste schon einen Multimediatimer.
|
Re: Ungenauigkeit von TDateTime / Alternative?
1/60 einer Sekunde ist ungefähr 17 Millisekunden.
Genauer als 17 Millisekunden geht dein Timer sowiso nicht. Da du in deinem ersten Versuch guckst, ob mehr als eine Sekunde vergangen ist, kann es duchaus passieren, dass mal nicht eine Sekunde, sondern 10-25 Millisekunden vergangen sind. Wenn jetzt zwischen jeder Aktion 1 Sekunde und 17 Millisekunden vergehen hast du nach 59 Aktionen ... tadaaa 60 Sekunden benötigt. Der zweite Versuch funktioniert, da er nicht immer auf die letzte Aktion zurückblickt (die ja einen Hauch verspätet eingetreten ist) sondern an den Anfang. |
Re: Ungenauigkeit von TDateTime / Alternative?
Hallo Michael,
Also die kleinste Abtastrate (mit Standardkomponenten) ist 16 ms (ungefähr), aber das ist eher nebensächlich. Ich wollte halt nur gesagt haben, das der Timer nicht zwingend jede Millisekunde ausgeführt wird. Zudem würde ich, wenn es nicht hundertprozentig eine Sekunde sein sollen (also 1,015 Sekunden würden auch gehen), würde ich statt ein TDateTime einfach GetTickCount also Cardinal nehmen.
Delphi-Quellcode:
Oder alternativ einfach das Intervall auf einer Sekunde belassen? Oder was spricht dagegen?
var
LastTick : Cardinal; procedure ...Timer(... begin if GetTickCount - LastTick >= 1000 then begin ... LastTick := GetTickCount; end; end; MfG xZise |
Re: Ungenauigkeit von TDateTime / Alternative?
erstmal danke für die schnellen Antworten.
Zum Timer Intervall: ja mir ist klar das der Timer nicht wirklich jede Millisekunde aufgerufen wird. Ich wollte auch nur das kleinstmöglichste Intervall erreichen und das hab ich so ja ^^ Wegen dem Intervall von einer Sekunde: Ich hatte halt überlegt das die Timer sicher nicht so wahnsinnig genau ist. Und wenn er jedesmal erst nach 1,1 Sekunden auslöst hab ich ja nach 10 Sekunden eine Sekunde verloren. Deshalb die Lösung mit dem kleineren Intervall, so dass ich eben früher merke wann die nächste Sekunde anfängt. Zitat:
Meine Fummel-Lösung mit dem Vergleich zweir FormatDateTime Ausdrücke hat jetzt jedenfalls 20 min lang perfekt funktioniert. Auch wenns mir irgendwie sehr gefrickelt vorkommt. |
Re: Ungenauigkeit von TDateTime / Alternative?
Dabei sollte man vielleicht auch wissen, dass GetTickCount alle 55ms hochgezählt wird. Das sind dann 18.2mal pro Sekunde. Kleiner als 55ms wird es nicht gehen, das hat Billy damals unter DOS so definiert.
|
Re: Ungenauigkeit von TDateTime / Alternative?
Wenn es wirklich darauf ankommt zeitgenau etwas auszuführen, dann ist Windows die flasche Platform. Windows ist kein real-time Betriebssystem. Windows basiert auf Nachrichten. Das heißt, nicht man selber bestimmt, ob ein Ereignis eintritt, sondern der Gegenüber und man reagiert dann auf das Ereignis. Wobei hier Ereignis nicht unbedingt im OOP Sinne zu betrachten ist.
Das heißt, für deine Aufgabe hast du das falsche Betriebssyste. Warum muss denn unbedingt genau jede Sekunde etwas ausgeführt werden? Und was passiert, wenn das nicht der Fall ist? Eine saubere Lösung wäre von der Zeitabhängigkeit weg zu kommen und ereignisorientiert zu arbeiten. |
Re: Ungenauigkeit von TDateTime / Alternative?
Zitat:
Wenn du wirklich darauf warten möchtest, dass der Sekundenzeiger umspringt, musst du wohl immer die aktuelle Sekunde ausrechnen lassen. |
Re: Ungenauigkeit von TDateTime / Alternative?
Zitat:
Warum jede Sekunde? Nun ich hab zurzeit eine miese Internetverbindung und infolgedessen mal mehr und mal weniger Paket Loss. Mit meinem Programm möchte ich also um das ganze etwas zu überwachen, zu protokollieren und im Nachhinein zu Analysieren halt beständig eine Internetseite anpingen und mir die Antwortzeit merken bzw. ob es ein Timeout = Paketverlust gab. Der sekündliche ping unter cmd.exe reicht da als Indikator schon aus. Wenn ich in einem Onlinespiel beispielsweise viele Lags (infolge von Paket Loss, wenn der Ping durchkommt ist die Antwort Zeit ok) hab, dann hab ich auch beim ping oft Zeitüberschreitungen. Und um halt mal festzuhalten zu welchen Tageszeiten ich durchschnittlich wieviel Paketverlust hatte brauche ich halt beständige Daten. Da nützt es mir nix wenn ich einfach so oft pinge wies geht und wenn dann ein Paket verloren geht einfach 2 sek warte bis ich es als timeout zähle und dann weiterpinge. Das gäbe eine reichlich sinnfreie Statistik. Ob meine Statistik jetzt sinnvoller ist sei mal dahingestellt ^^ Ist für meine Frage auch egal Zitat:
danke an alle für die hilfe:) edit: Ich werds dann aber wohl folgendermaßen lösen:
Delphi-Quellcode:
sieht nicht mehr ganz so gruselig aus und müsste auch funktionierenif SecondOf(Now)>SecondOf(myPingModul.LastePing) then begin |
Re: Ungenauigkeit von TDateTime / Alternative?
Ich würde im Timer-Ereignis einfach das Interval in Abhängigkeit von der Ungenauigkeit korrigieren. Hier ein Schnippel;
Delphi-Quellcode:
Läuft wie ein Uhrwerk :mrgreen:
Procedure TForm1.StartButtonClick (Sender : TObject);
Begin Timer1.Interval := 1000; Start := Now; NumberOfSeconds := 0; Timer1.Enabled := True; End; procedure TForm16.Timer1Timer(Sender: TObject); Var elapsed : Double; begin elapsed := 86400*(Now-Start); inc (NumberOfSeconds ); Timer1.interval := Trunc(1000*(1 - Elapsed + NumberOfSeconds )); // Interval korrigieren // Test-Code zum Anzeigen: Anzahl der Sekunden, vergangene Sekunden seit Start, korrigiertes Interval Memo1.Lines.add(Format('%.4d %8.1f %4d',[NumberOfSeconds , elapsed, timer1.interval])); end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:44 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz