AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Ungenauigkeit von TDateTime / Alternative?

Ein Thema von Antigo · begonnen am 27. Mär 2009 · letzter Beitrag vom 28. Mär 2009
Antwort Antwort
Antigo

Registriert seit: 14. Mär 2005
274 Beiträge
 
#1

Ungenauigkeit von TDateTime / Alternative?

  Alt 27. Mär 2009, 23:31
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:
Flastaction: TDateTime;
//...
FLastAction:=Now;
Dann frage ich in jedem Timer Aufruf

Delphi-Quellcode:
if SecondsBetween(Now,FLastAction) > 0 then
  //Stoße nächste Aktion an, speicher Now als FlastAction und als Startpunkt der Aktion
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.

Jetzt hab ich testweise etwas ganz blödes gemacht und statt secondsbetween folgendes benutzt:
Delphi-Quellcode:
if FormatDateTime('ss',Now)<>FormatDateTime('ss',FLastAction) then
    //Stoße nächste Aktion an, speicher Now als FlastAction und als Startpunkt der Aktion
und jetzt habe ich plötzlich durchgehend meine 60 Aktionen pro Minute.

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?

Michael
"How should I know if it works? That's what beta testers are for. I only coded it."
  Mit Zitat antworten Zitat
Benutzerbild von Die Muhkuh
Die Muhkuh

Registriert seit: 21. Aug 2003
7.332 Beiträge
 
Delphi 2009 Professional
 
#2

Re: Ungenauigkeit von TDateTime / Alternative?

  Alt 27. Mär 2009, 23:36
Mit nem Timer bekommste sowieso keine 1ms hin, da brauchste schon einen Multimediatimer.
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#3

Re: Ungenauigkeit von TDateTime / Alternative?

  Alt 27. Mär 2009, 23:42
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.
  Mit Zitat antworten Zitat
Benutzerbild von xZise
xZise

Registriert seit: 3. Mär 2006
Ort: Waldbronn
4.303 Beiträge
 
Delphi 2009 Professional
 
#4

Re: Ungenauigkeit von TDateTime / Alternative?

  Alt 27. Mär 2009, 23:45
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:
var
  LastTick : Cardinal;

procedure ...Timer(...
begin
  if GetTickCount - LastTick >= 1000 then
  begin
    ...
    LastTick := GetTickCount;
  end;
end;
Oder alternativ einfach das Intervall auf einer Sekunde belassen? Oder was spricht dagegen?

MfG
xZise
Fabian
Eigentlich hat MS Windows ab Vista den Hang zur Selbstzerstörung abgewöhnt – mkinzler
  Mit Zitat antworten Zitat
Antigo

Registriert seit: 14. Mär 2005
274 Beiträge
 
#5

Re: Ungenauigkeit von TDateTime / Alternative?

  Alt 27. Mär 2009, 23:56
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 von jfheins:
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.
Werden bei TdateTime denn auch die millisekunden mitgespeichert? Wenn ja dann stimmt das natürlich weil ich ja dann darauf warte, dass seit der letzten Aktion mind 1 Sekunde vergangen ist. Ich will ja aber darauf warten, dass der Sekundenzeiger umspringt, also FormatDateTime('ss',Now) eine andere Zeit ausspuckt, als bei der letzten Aktion und da hilft mir ein GettickCount auch nicht weiter.

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.
Michael
"How should I know if it works? That's what beta testers are for. I only coded it."
  Mit Zitat antworten Zitat
omata

Registriert seit: 26. Aug 2004
Ort: Nebel auf Amrum
3.154 Beiträge
 
Delphi 7 Enterprise
 
#6

Re: Ungenauigkeit von TDateTime / Alternative?

  Alt 27. Mär 2009, 23:57
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.
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#7

Re: Ungenauigkeit von TDateTime / Alternative?

  Alt 28. Mär 2009, 00:05
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.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#8

Re: Ungenauigkeit von TDateTime / Alternative?

  Alt 28. Mär 2009, 00:15
Zitat von Antigo:
Werden bei TdateTime denn auch die millisekunden mitgespeichert? Wenn ja dann stimmt das natürlich weil ich ja dann darauf warte, dass seit der letzten Aktion mind 1 Sekunde vergangen ist. Ich will ja aber darauf warten, dass der Sekundenzeiger umspringt, also FormatDateTime('ss',Now) eine andere Zeit ausspuckt, als bei der letzten Aktion und da hilft mir ein GettickCount auch nicht weiter.
WSenn mich nicht alles täuscht ist TDateTime ein Double. Der kommt noch gut in den Millisekundenbereich hinein (von der Genauigkeit) der hier bei etwa 2*10^-7 liegt.

Wenn du wirklich darauf warten möchtest, dass der Sekundenzeiger umspringt, musst du wohl immer die aktuelle Sekunde ausrechnen lassen.
  Mit Zitat antworten Zitat
Antigo

Registriert seit: 14. Mär 2005
274 Beiträge
 
#9

Re: Ungenauigkeit von TDateTime / Alternative?

  Alt 28. Mär 2009, 00:18
Zitat von Luckie:
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.
joar ist mir alles klar aber ich möchte auch kein auf ms genaues Programm haben. Und auf eine Sekunde genau sollte möglich sein. Klappt ja auch mit der Gerfrickelten Lösung ganz gut.

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 von jfheins:
Zitat von Antigo:
Werden bei TdateTime denn auch die millisekunden mitgespeichert? Wenn ja dann stimmt das natürlich weil ich ja dann darauf warte, dass seit der letzten Aktion mind 1 Sekunde vergangen ist. Ich will ja aber darauf warten, dass der Sekundenzeiger umspringt, also FormatDateTime('ss',Now) eine andere Zeit ausspuckt, als bei der letzten Aktion und da hilft mir ein GettickCount auch nicht weiter.
WSenn mich nicht alles täuscht ist TDateTime ein Double. Der kommt noch gut in den Millisekundenbereich hinein (von der Genauigkeit) der hier bei etwa 2*10^-7 liegt.

Wenn du wirklich darauf warten möchtest, dass der Sekundenzeiger umspringt, musst du wohl immer die aktuelle Sekunde ausrechnen lassen.
Das muss ich dann wohl :s


danke an alle für die hilfe


edit: Ich werds dann aber wohl folgendermaßen lösen:
Delphi-Quellcode:
  
  if SecondOf(Now)>SecondOf(myPingModul.LastePing) then
  begin
sieht nicht mehr ganz so gruselig aus und müsste auch funktionieren
Michael
"How should I know if it works? That's what beta testers are for. I only coded it."
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#10

Re: Ungenauigkeit von TDateTime / Alternative?

  Alt 28. Mär 2009, 10:07
Ich würde im Timer-Ereignis einfach das Interval in Abhängigkeit von der Ungenauigkeit korrigieren. Hier ein Schnippel;

Delphi-Quellcode:
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;
Läuft wie ein Uhrwerk
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:01 Uhr.
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