跟踪时间的准确方法

本文关键字:方法 时间 跟踪 | 更新日期: 2023-09-27 18:34:30

对于我的应用程序,我必须跟踪时间变化,以"平滑"时间变化。

发生系统时间更改的原因有多种:

  • 用户更改其系统时间
  • 操作系统 NTP 服务器更新本地时间

所以实际上我们有一个"时间提供程序",它为整个应用程序提供当前时间。

目标是检测是否发生时间偏移并顺利地纠正我们的本地时间(例如,如果我们有一个小时的"时间跳跃",每秒纠正 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 秒的推导,如果我只是将 1000ms 替换为 10000ms,我很快就会得到 1ms 到 0.5ms 之间的时间推导。

所以我的问题(最后:P(:

  1. 为什么两个Utc.DateTime给了我这么多差异?它们都是基于时钟滴答声不是吗?
  2. 难道没有办法更精确地获得这个时间转移吗?

跟踪时间的准确方法

  1. 不,它们并非都基于时钟滴答声。 Stopwatch可能是高分辨率或低分辨率。如果分辨率低,则在下面使用DateTime.UtcNow。不幸的是,您无法选择它是高还是低,因此:

  2. 创建自己的"秒表",始终使用下面的DateTime.UtcNow

编辑

这是(2.(中的一个愚蠢的建议,你显然需要避免DateTime.UtcNow因为这是你试图纠正的。我建议你看看在刻度中工作,我的意思是 1/10000 秒,以匹配高分辨率Stopwatch.这是因为TimeSpan只能精确到 1/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无论如何都适用于整个系统,所以写你自己的。