2013-11-01 18 views
6

私は1msよりも正確に時間を報告するタイムサービスを実装しようとしています。簡単な解決策は、初期測定を行い、StopWatchを使ってデルタを追加することだと思いました。問題は、この方法が壁の時間から非常に速く発散しているように見えることです。たとえば、次のコードは、ウォール時間と私の高分解能クロックの乖離を測定しようとします。C#で高解像度のDateTime.UtcNowを実装する最も良い方法は?

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); 
    } 
} 

私はかなり最近のサーバのハードウェアで約2ミリ秒/分の速度で発散しています。

私はそれがより正確になることに気づいていない別の時間機能がウィンドウにありますか?そうでない場合は、高解像度の時計や私が使用するはずのサードパーティライブラリを作成する方が良いでしょうか?

+2

質問: 'DateTime.UtcNow'があなたのために十分正確でない場合、あなたはあなたのタイムサービスをシードするために何を使用しますか? – StriplingWarrior

+0

@ Hansの偉大な答えに加えて、ハードウェアデバイス( "高価な水晶発振器"のもの)を使ってこれを達成しようとするかもしれないと付け加えたいと思います。 Windowsのボックスでサブミス時間を転送できるかどうかは分かりません。 –

答えて

8

正確な時計を取得することは困難です。ストップウォッチは非常に高い分解能を持ちますが、正確ではなく、チップセット内の信号からその周波数を導き出します。典型的な電子部品公差で動作する。ハードウェア事業における競争激しい競争は、保証された安定した周波数の高価な水晶振動子を先取りしたものでした。

DateTime.UtcNowはそのどれも正確ではありませんが、ヘルプが表示されます。 Windowsは定期的にタイムサービスに接続し、デフォルトのものはtime.windows.comで、高品質のクロックのアップデートを取得します。それを使用して機械の時計を再校正し、小さな調整を挿入して時計が追いつくか遅くなるようにします。

ミリ秒まで正確に取得するには、もっと大きなトリックが必要です。カーネルモードで実行され、割り込み優先順位で実行されるコードで、他のコードやコードとデータページがページロックされているため、ページフォールトでヒットできないような保証が得られるだけです。商用ソリューションは、GPS衛星のクロック信号を読み取るためにGPS無線機を使用し、温度安定性を提供するためにオーブン内で動作する発振器によってバックアップされる。そのような時計を読むことは難しい問題です。時間が得られたときと同じようにオペレーティングシステムによってプリエンプトされたプログラムが使用されてから、再度実行を開始しないと、ミリ秒以下のクロックソースにはあまり使用しません。約45ミリ秒後。または悪い。

DateTime.UtcNowは15.625ミリ秒に正確であり、タイムサービスの更新によって非常に長い期間にわたって安定しています。それを下回ることはあまり意味がありません。ユーザーモードで実行を保証することはできません。

4

明らかにWindows 8/Server 2012には、高解像度のタイムスタンプを取得するための新しいAPI、具体的にはGetSystemTimePreciseAsFileTime APIが追加されています。私はこれで遊ぶ機会はなかったが、それは有望に見える。

関連する問題