Holen Sie sich Zeit in Millisekunden mit C #

131

Ich mache ein Programm, in dem ich die Zeit in Millisekunden bekommen muss. Mit Zeit meine ich eine Zahl, die niemals gleich ist und immer 1000 Zahlen größer ist als vor einer Sekunde. Ich habe versucht, DateTime.Nowzu einem zu konvertieren TimeSpanund das TotalMillisecondsdaraus zu machen ... aber ich habe gehört, dass es nicht ganz genau ist.

Gibt es einen einfacheren Weg, dies zu tun?

Entität
quelle
Erwarten Sie, dass zwei Anrufe immer zu steigenden Werten führen? Im Allgemeinen ergeben Anrufe, die näher als das Mindestintervall sind, das die Timerauflösung zulässt, denselben Wert. Sie müssten Ihren eigenen Tiebreaker in Form eines Serializers mit gefälschter Präzision hinzufügen.
Steven Sudit
16
"Eine Zahl, die niemals gleich ist". Das klingt ... kompliziert. ;)
Mizipzor
NaN würde diese Anforderung tatsächlich erfüllen. Obwohl es "keine Zahl" ist, ist es ein Zahlentyp und nicht gleich sich selbst.
Yay295

Antworten:

78

Verwenden Sie die StopwatchKlasse.

Bietet eine Reihe von Methoden und Eigenschaften, mit denen Sie die verstrichene Zeit genau messen können.

Hier finden Sie einige gute Informationen zur Implementierung:

Leistungstests: Präzise Laufzeitmessungen mit System.Diagnostics.Stopwatch

RedFilter
quelle
8
Stoppuhr ist Teil der Diagnose. Sollte es in echtem Code verwendet werden?
Andrey
Dies ist normalerweise nur auf die nächsten 15 ms oder so genau.
Steven Sudit
11
Wie teuer ist es aber? Vielleicht sollten wir eine Stoppuhr stoppen :)
jb.
3
@Steven, das hängt vom Betriebssystem und der zugrunde liegenden Hardware ab. Falls verfügbar, wird ein hochauflösender Timer verwendet. Dies ist bei allen mir bekannten aktuellen Desktop- und Server-basierten x86-Windows-Versionen der Fall. Überprüfen Sie die Eigenschaften Frequenz und IsHighResolution für weitere Details. Auf Betriebssystemebene sind QueryPerformanceCounter und QueryPerformanceFrequency die APIs auf niedriger Ebene, die diese Funktionalität unterstützen.
Chris Taylor
320
long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;

So werden die verschiedenen Unix-Konvertierungsmethoden in der DateTimeOffsetKlasse implementiert (.NET Framework 4.6+, .NET Standard 1.3+):

long milliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();
Evan Mulawski
quelle
65
Der Titel lautet "Zeit in Millisekunden abrufen". Diese Antwort ist hilfreich.
Luft- und Raumfahrt
33
Ja, für diejenigen von uns, die nach einer Antwort auf die gestellte Frage suchen, war dies sehr hilfreich, danke.
user430788
1
Wenn Sie Dezimalstellen möchten (auch wenn diese DateTime.Nownicht sehr oft "aktualisiert" werden), verwenden Sie decimal milliseconds = DateTime.Now.Ticks / (decimal)TimeSpan.TicksPerMillisecond;stattdessen stattdessen.
Jeppe Stig Nielsen
1
Dies ist viel nützlicher als die ausgewählte Antwort für Suchergebnisse und sogar für das, was ich aus der ursprünglichen Frage erhalte.
Bwoogie
1
Diese Antwort hat mir das Leben gerettet. Habe ähnlichen Code, funktioniert aber nicht. Konnte nicht herausfinden warum. Dann sah ich den longDatentyp vor Millisekunden. Mit intsicherlich wird überlaufen.
FisNaN
13

Das DateTime.Ticks Eigenschaft erhält die Anzahl der Ticks, die Datum und Uhrzeit darstellen.

10.000 Ticks sind eine Millisekunde (10.000.000 Ticks pro Sekunde).

Itay Karo
quelle
4
Aber die Auflösung von Zecken ist sehr viel weniger als 1 / 10000s, vielleicht 1 /
62s
2
@ Codymanix - von MSDN:A single tick represents one hundred nanoseconds or one ten-millionth of a second. There are 10,000 ticks in a millisecond.
Itay Karo
5
Sicher ist es das, aber das Betriebssystem hat nicht die Auflösung, um genau zu sein.
Codymanix
6
@codymanix ist korrekt. In Analogie ist ein Angstrom eine Längeneinheit; Zehn Milliarden Angström machen einen Meter. Sie könnten eine Funktion schreiben, die Ihre Größe in Angström als 64-Bit-Ganzzahl angibt. Wenn Sie jedoch nur einen zentimetergenauen Metrestick haben, ist die Tatsache, dass die Funktion eine Genauigkeit im Subnanometerbereich darstellt, völlig irrelevant. Die weniger bedeutenden Ziffern werden Müll sein.
Eric Lippert
4
@ RedFilter: Wenn Sie Ihr Alter tatsächlich auf die nächste Millisekunde genau kennen, könnten Sie möglicherweise etwas sagen wie: "Wenn ich wieder blinke, beträgt mein Alter x Millisekunden." Das tiefere Problem ist nicht die Kommunikation, sondern die Messung: Es ist unwahrscheinlich, dass Ihre Geburt bis zur nächsten Sekunde bekannt ist.
Steven Sudit
11

Ich benutze die folgende Klasse. Ich habe es einmal im Internet gefunden und postuliert, es sei das beste JETZT () .

/// <summary>Class to get current timestamp with enough precision</summary>
static class CurrentMillis
{
    private static readonly DateTime Jan1St1970 = new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    /// <summary>Get extra long current timestamp</summary>
    public static long Millis { get { return (long)((DateTime.UtcNow - Jan1St1970).TotalMilliseconds); } }
}

Quelle unbekannt.

schmijos
quelle
5
FWIW, der ganze Sinn dieses häufig verwendeten Snippets, besteht darin, einen Zeitstempel zu erstellen, der mit dem Unix-Zeitstempelstandard kompatibel ist. Dafür ist es wichtig. Wenn man nur das Timing machen will, ist es unnötig teuer.
ToolmakerSteve
8

Sie können die QueryPerformanceCounternative Methode ausprobieren . Weitere Informationen finden Sie unter http://www.pinvoke.net/default.aspx/kernel32/QueryPerformanceCounter.html . Dies ist, was die StopwatchKlasse verwendet.

Siehe So erhalten Sie einen Zeitstempel für die Tick-Genauigkeit in .NET / C # für mehr Informationen.

Stopwatch.GetTimestamp() gibt Zugriff auf diese Methode:

public static long GetTimestamp() {
     if(IsHighResolution) {
         long timestamp = 0;
         SafeNativeMethods.QueryPerformanceCounter(out timestamp);
         return timestamp;
     }
     else {
         return DateTime.UtcNow.Ticks;
     }
 }
Pieter van Ginkel
quelle
1
AFAIK StopWatch verwendet QueryPerformanceCounter intern, falls verfügbar
Codymanix
Ja, die interne Implementierung von Stopwatch.GetTimestamp()bietet tatsächlich Zugriff auf diese Methode.
Pieter van Ginkel
5

Ich habe DateTime.Now.TimeOfDay.TotalMilliseconds (für den aktuellen Tag) verwendet, hoffe, es hilft Ihnen auch.

Sarvan
quelle
1
Dadurch werden keine steigenden Werte zurückgegeben (wie für das Originalposter erforderlich), da TimeOfDay täglich um Mitternacht auf Null zurückgesetzt wird. Außerdem hätte es die gleichen potenziellen Probleme, die das Poster bei der Verwendung von DateTime erwähnt hat. Jetzt werden die gesamten Millisekunden daraus abgerufen.
Jim O'Neil
3
Jim O'Neil Ich stimme dir zu, deshalb habe ich in meinem Beitrag "(für den aktuellen Tag)" erwähnt ... Übrigens, meine Lösung hat für mein Problem funktioniert, da mein Problem nicht datumsspezifisch ist, ich musste es einfach bekommen Der Millisekunden-Teil soll als Zähler verwendet werden, also habe ich ihn hier gepostet. Ich bin neu hier, also wenn ich es an einer falschen Stelle gepostet habe, tut es mir leid :)
Sarvan
2

Verwenden Sie System.DateTime.Now.ToUniversalTime(). Dadurch wird Ihr Messwert in ein bekanntes referenzbasiertes Millisekundenformat gebracht, das Tagesänderungen usw. vollständig eliminiert.

John Tobler
quelle
Gut zu wissen, aber nicht relevant für die gestellte Frage, bei der es um das Timing (Messung des Zeitablaufs) geht, nicht um die genaue Kommunikation der Zeit.
ToolmakerSteve