Laden...

Ungenauigkeiten bei Timern vermeiden

Erstellt von hlag vor 11 Jahren Letzter Beitrag vor 11 Jahren 1.910 Views
H
hlag Themenstarter:in
8 Beiträge seit 2013
vor 11 Jahren
Ungenauigkeiten bei Timern vermeiden

Hallo Leute,

ich suche eine Funktion, die mir halbwegs solide sowas wie eine Zeitbasis in Millisekunden zur Verfügung stellt.

Mein erster Versuch war

(int)(DateTime.Now.Ticks/10000)

Dies habe ich mit einem Thread abgerufen, der im 10 ms-Rhytmus arbeitet.
Ich erwarte, dass die so ausgegebenen Zeiten um mindestens 10 ms differieren (10 ms sleep + Arbeitszeit eines Zyklus). Ich bekam aber regelmäßig in zwei aufeinanderfolgenden Zyklen die exakt gleiche Zeit

Zweiter Versuch:

Timer in:


namespace Hlag
{
    class hlagTimer
    {


        private static int ms = 0;
        public static void start()
        {
            System.Timers.Timer aTimer = new System.Timers.Timer();

            // Hook up the Elapsed event for the timer.
            aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);

 
            aTimer.Interval = 1;
            aTimer.Enabled = true;

        }

        // Hier folgen die Anweisungen im im Timer
        private static void OnTimedEvent(object source, ElapsedEventArgs e)
        {
            ms += 1;
        }


        public static int get()
        {
            return ms;
        }
    }
}

Hab die Ausgabe gegen DateTime abgeglichen, mein Timer läuft um ca. Faktor 8 langsamer als DateTime.

Nächster Versuch war die Stopwatch, die läuft aber etwa doppelt so schnell wie DateTime.

Nach etwa einer halben Minute hatte ich folgende Werte:

Mein Timer: 2321 ms
DateTime: 36140 ms
Stopwatch: 72263 ms

Bei dem Unterschied zwischen MeinTimer und DateTime könnte man noch einen Rechenfehler um Fakto 10 vermuten, ist aber nicht. Wenn ich das intervall meines Timers auf 100 ms setze, läuft der zu DateTime vergleichsweise parallel (+/- 5 %)

Zum DateTime Gedöhns hab ich im Netz irgendwo gefunden, dass das gute Stück wohl nur im 10 ms Takt aktualisiert würde...

Wo bekomme ich denn eine vernünftige Zeit als Basis her?

Viele Grüße,

Klaus

Auch die schönste Frau
ist an den Füßen
zu Ende.

C
2.121 Beiträge seit 2010
vor 11 Jahren

Timer sind nicht zu 100% genau. Das liegt schon mal daran dass das Betriebssystem deinen Prozess immer wieder schlafen legt und er somit nicht zur genau richtigen Zeit aktiv sein kann. 10 ms dürfte an der Grenze liegen, die überhaupt annähernd minimal aufgelöst werden kann.
Die Millisekunden per Timer zählen ist also keine gute Idee.

Die Ticks von DateTime und Stopwatch müssen (fast) gleich sein, was da schief läuft kann ich nicht verstehen.
Wenns eine halbe Minute war, ist DateTime der korrekte Wert. Wie hast du die StopWatch genutzt?

16.833 Beiträge seit 2008
vor 11 Jahren

Der MultimediaTimer ist der genaueste, siehe dazu auch Timer surprises, and how to avoid them
Hier sind aber die Beschränkungen zu beachten.

Dazu gibts auch unzählige Treffer hier im Forum: [Hinweis] Wie poste ich richtig? 1.1

Zur Resolution von Timern hat chilic ja schon das nötigste gesagt: 100% gibts unter Windows einfach nicht, da kein Echtzeitsystem.

849 Beiträge seit 2006
vor 11 Jahren

Hallo,

Die Ticks von DateTime und Stopwatch müssen (fast) gleich sein, was da schief läuft kann ich nicht verstehen.

Sollte man meinen, ist aber nicht so. Ticks DateTime sind meist != Stopwatch Ticks.

Dazu einmal doc DateTime

Zeitwerte werden in Einheiten von 100 Nanosekunden gemessen, die als Ticks bezeichnet werden

Und Doc Stopwatch

Die Stopwatch misst verstrichene Zeit, indem sie die Ticks des Zeitgebers im zugrunde liegenden Zeitgebermechanismus zählt.Wenn die installierte Hardware und das Betriebssystem einen hochauflösenden Leistungsindikator unterstützen, wird dieser von der Stopwatch-Klasse zum Messen der verstrichenen Zeit verwendet.

(interessant sind hier auch die Propertys IsHighResulution und Frequenzy)

Zum Vergleich auf meinem System wird eine Frequenzy von 3 335 136 /s angegeben, was ~ 299 nano pro Tick wären. (DateTime -> 100 nano pro Tick s.o.)

Deshalb zählt in diesem Codeschnipsel (auf meinem Rechner) die Stopwatch immer "langsamer":


for (int i = 0; i < 100;i++ )
			{
				var time = DateTime.Now;
				//var ticks = DateTime.Now.Ticks;				

				

				var stopwatch = new Stopwatch();
				stopwatch.Start();
					Thread.Sleep(10);
				stopwatch.Stop();
				
				long stopWatchTicks = stopwatch.ElapsedTicks;

				var freq = Stopwatch.Frequency;
				double secPerTick= 1d / freq;
				var timeEnd = DateTime.Now;
				Console.WriteLine("ticksStart: {0} , ticksEnd: {1}, sleepForDateTimeTicks:{2}, sleepStopWatchTicks {3}", time.Ticks, timeEnd.Ticks, timeEnd.Ticks - time.Ticks, stopWatchTicks);
			}

Das heisst aber nicht das DateTime genauer ist, weils die die größere Auflösung hat. Wie ihr in diesem Beispiel auch seht, ist das sleepForDateTimeTicks meist ungefähr den selben Wert hat. Das liegt an dem schon erwähnten aktualisierungsInterval von DateTime.

Somit hat Stopwatch zwar die geringere Auflösung (In meinem Fall.. Hardwareabhänging) aber ist trotzdem genauer.

Und auch von mir: Weder Windows noch .net sind Echtzeitsysteme 😦

Gruß

U
1.688 Beiträge seit 2007
vor 11 Jahren

Sollte man meinen, ist aber nicht so. Ticks DateTime sind meist != Stopwatch Ticks.

Oben steht aber "ms", nicht Ticks. Wobei auffällt, dass die Stopwatch nahezu exakt das Doppelte von DateTime anzeigt.

Der Multimediatimer hat im übrigen eine Auflösung von (bestenfalls) 1ms, die er auch (im Mittel) einhält. Aber das ist bei 10ms ähnlich, wobei da die einzelne Abweichung natürlich nicht so ins Gewicht fällt.

849 Beiträge seit 2006
vor 11 Jahren

Ich bin einmal davon ausgegangen das die ms genau so berechnet wurden wie bei DateTime also x/10000

Wobei mich interessieren würde wie diese Frequencys auf anderen Rechnern sind.. im Speziellen ob es welche gibt die die 100ns/Tick unterschreiten was o.g. Zeiten erklären würde. Aber das ist wohl offtopic

C
2.121 Beiträge seit 2010
vor 11 Jahren

Ok den entsprechenden Teiler sollte man natürlich schon berücksichtigen 😃
ABer bei DateTime gibt es keinen (bzw. wird intern gemacht), von daher muss die damit gemessene Zeit ziemlich korrekt sein.
Eine andere Idee wäre noch Environment.TickCount, das ist auch ein festgelegtes Intervall ohne weitere Rechnung.

H
hlag Themenstarter:in
8 Beiträge seit 2013
vor 11 Jahren
Erster Fehler gefunden

Hallo Leute,

die Ticks der Stopwatch sind nicht identisch mit den Ticks von DateTime.

Stopwatch liefert 200 Ticks, wo DateTime nur einen liefert.

Seltsames Verhältnis, die Anzahl Nullen hatte ich korrigiert, die Zwei konnte ich mir nicht vorstellen...

Jetzt laufen beide Uhren mit einem Versatz von zehn Millisekungen zumindest schonmal gleichsinnig.

Weitere Tests werden folgen...

Auch die schönste Frau
ist an den Füßen
zu Ende.

2.891 Beiträge seit 2004
vor 11 Jahren

Wobei mich interessieren würde wie diese Frequencys auf anderen Rechnern sind.. im Speziellen ob es welche gibt die die 100ns/Tick unterschreiten was o.g. Zeiten erklären würde.

Ich habe mal auf einem Serversystem getestet: Frequenzangabe ist 62.500.000, was 16ns/Tick entsprechen würde.