2013-11-01 8 views
6

Ich versuche, einen Zeitdienst zu implementieren, der Zeit mit größerer Genauigkeit als 1ms meldet. Ich dachte, eine einfache Lösung wäre, eine erste Messung durchzuführen und StopWatch zu verwenden, um ein Delta hinzuzufügen. Das Problem ist, dass diese Methode extrem schnell von der Wandzeit abzuweichen scheint. Zum Beispiel versucht der folgende Code die Divergenz zwischen Wand Zeit und meiner Hohen Auflösung Uhr zu messen:Der beste Weg, um eine hohe Auflösung DateTime.UtcNow in C# zu implementieren?

public static void Main(string[] args) 
{ 
    System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch(); 
    DateTime baseDateTime = DateTime.UtcNow; 
    s.Start(); 
    long counter = 0; 
    while(true) 
    { 
     DateTime utcnow = DateTime.UtcNow; 
     DateTime hpcutcnow = baseDateTime + s.Elapsed; 
     Console.WriteLine(String.Format("{0}) DT:{1} HP:{2} DIFF:{3}", 
      ++counter, utcnow, hpcutcnow, utcnow - hpcutcnow)); 
     Thread.Sleep(1000); 
    } 
} 

Ich divergierend mit einer Rate von etwa 2 ms/Minute auf relativ neue Sever-Hardware.

Gibt es eine andere Zeitfunktion in Windows, von der ich nicht weiß, dass sie genauer ist? Wenn nicht, gibt es einen besseren Ansatz zum Erstellen einer Uhr mit hoher Auflösung oder einer 3rd-Party-Bibliothek, die ich verwenden sollte?

+2

Frage: Wenn 'DateTime.UtcNow' nicht genau genug für Sie ist, was werden Sie verwenden, um Ihren Zeitdienst zu erstellen? – StriplingWarrior

+0

Zusätzlich zu @ Hans 'großer Antwort würde ich hinzufügen, dass Sie versuchen könnten, dies mit einem Hardwaregerät (etwas mit "einem teuren Quarzoszillator") zu erreichen. Ich bin mir nicht sicher, ob Sie Sub-ms-Zeit auf einer Windows-Box übertragen und nutzen können. –

Antwort

8

Eine genaue Uhr zu bekommen ist schwierig. Stoppuhr hat eine sehr hohe Auflösung, aber es ist nicht genau, abgeleitet seine Frequenz von einem Signal im Chipsatz. Das funktioniert bei typischen Elektroniktoleranzen. Verdrängungswettbewerb im Hardware-Geschäft hat die teuren Quarzoszillatoren mit einer garantierten und stabilen Frequenz verdrängt.

DateTime.UtcNow ist auch nicht so genau, aber es bekommt Hilfe. Windows kontaktiert regelmäßig einen Zeitdienst, der Standard ist time.windows.com, um eine Aktualisierung einer hochwertigen Uhr zu erhalten. Und verwendet es, um die Uhr der Maschine neu zu kalibrieren und kleine Anpassungen vorzunehmen, um die Uhr aufzuschließen oder zu verlangsamen.

Sie benötigen viele größere Tricks, um es auf eine Millisekunde genau zu erhalten. Sie können nur eine Garantie wie diese für Code erhalten, der im Kernel-Modus läuft, mit Unterbrechungspriorität, so dass er nicht durch anderen Code vorweggenommen werden kann und seine Code- und Datenseiten page-locked, so dass er nicht mit Seitenfehlern getroffen werden kann . Kommerzielle Lösungen verwenden ein GPS-Funkgerät, um das Taktsignal der GPS-Satelliten zu lesen, unterstützt von einem Oszillator, der in einem Ofen läuft, um Temperaturstabilität bereitzustellen. Das Auslesen einer solchen Uhr ist das schwere Problem, Sie brauchen für eine Unter-Millisekunden-Taktquelle nicht viel zu gebrauchen, wenn Ihr Programm, das es benutzt, vom Betriebssystem vorweggenommen werden kann, so wie es die Zeit erhalten hat und nicht wieder zu laufen beginnt ~ 45 ms später. Oder schlimmer.

DateTime.UtcNow ist auf 15,625 Millisekunden genau und über sehr lange Zeiträume dank der Serviceaktualisierungen stabil. Wenn Sie tiefer gehen, ergibt das nicht viel Sinn. Sie können nicht die Ausführungsgarantie erhalten, die Sie im Benutzermodus benötigen, um davon profitieren zu können.

4

Offenbar wurde in Windows 8/Server 2012 eine neue API hinzugefügt, um die Timestamps mit hoher Auflösung, die GetSystemTimePreciseAsFileTime API, zu erhalten. Ich hatte keine Chance, damit herumzuspielen, aber es sieht vielversprechend aus.