0

私のアプリケーションでは、時間の変化を「滑らかにする」ために、時間の変化を追跡する必要があります。

システム時刻の変更は、いくつかの理由で発生する可能性があります。

  • ユーザーがシステム時刻を変更する
  • OS NTP サーバーは現地時間を更新します
  • ...

実際には、アプリケーション全体に現在の時刻を提供する「TimeProvider」があります。

目標は、タイム シフトが発生したかどうかを検出し、ローカル タイムをスムーズに修正することです (たとえば、1 時間の「タイム ジャンプ」がある場合、完全に修正されるまで毎秒 100 ミリ秒修正します)。

これが基本的に時間を提供する必要があるものです(現在、時間の変更を完全にスムーズにすることはしていませんが、現在の問題ではないことに注意してください)

internal class TimeChange : IDisposable
{
    private readonly Timer _timer;
    private readonly Stopwatch _watch = new Stopwatch();
    private DateTime _currentTime;

    public DateTime CurrentTime 
    {
        get { return _currentTime + _watch.Elapsed; }
    }

    public TimeChange()
    {
        _timer = new Timer(1000);
        _timer.Elapsed += OnTimerElapsed;
        _timer.Start();
        _watch.Start();
        _currentTime = DateTime.UtcNow;
    }

    public void Dispose()
    {
        _timer.Stop();
        _timer.Elapsed -= OnTimerElapsed;
    }

    private void OnTimerElapsed(object sender, ElapsedEventArgs e)
    {
        DateTime currentTime = DateTime.UtcNow;
        TimeSpan timeDerivation = currentTime - _currentTime - _watch.Elapsed;
        _watch.Restart();
        _currentTime = currentTime;
        Console.WriteLine("Derivation: " + timeDerivation.TotalMilliseconds + "ms");
    }
}

しかし、いくつかのテストを行うと、現地時間で何もしなくても違いがあることに気付きました。大きな違いはありませんが (<1ms)、それでも:

Press enter to stop
Derivation: -0.1367ms
Derivation: 0.9423ms
Derivation: 0.0437ms
Derivation: 0.0617ms
Derivation: 0.0095ms
Derivation: 0.0646ms
Derivation: -0.0149ms

これは 1 秒の微分です。1000 ミリ秒を 10000 ミリ秒に置き換えると、すぐに 1 ミリ秒から 0.5 ミリ秒の時間微分が得られます。

だから私の質問(最後に:P):

  1. なぜ2つの間にUtc.DateTimeそんなに多くの違いがあったのですか? どちらもクロック ティックに基づいています。
  2. このタイムシフトをより正確に取得する方法はありませんか?
4

1 に答える 1

1
  1. いいえ、どちらもクロックティックに基づいているわけではありません。Stopwatchハイレゾかローレゾかも。低解像度の場合は、DateTime.UtcNowundernei を使用します。残念ながら、高いか低いかを選択することはできません。

  2. 常にアンダーネイトを使用する独自の「ストップウォッチ」を作成しますDateTime.UtcNow

編集

DateTime.UtcNowそれは (2.) のばかげた提案です。修正しようとしていることは明らかに避ける必要があります。high-res と一致するように、1/10000 秒を意味するティックで作業することをお勧めしますStopwatch。これは、TimeSpan1/1000 秒の精度しかないためです。

番号 1. より詳細に:

Stopwatchこの方法を使用します:

public static long GetTimestamp()
{
    if (!Stopwatch.IsHighResolution)
    {
        DateTime utcNow = DateTime.UtcNow;
        return utcNow.Ticks; //There are 10,000 of these ticks in a second
    }
    else
    {
        long num = (long)0;
        SafeNativeMethods.QueryPerformanceCounter(out num);
        return num; //These ticks depend on the processor, and
                    //later will be converted to 1/10000 of a second
    }
}

しかし、私が言うように、IsHighResolution設定できないようで、staticとにかくシステム全体に適用されるので、自分で書いてください。

于 2013-10-09T12:33:57.410 に答える