准确的时间追踪方法

Posted

技术标签:

【中文标题】准确的时间追踪方法【英文标题】:Accurate method to track time 【发布时间】:2013-10-09 12:25:04 【问题描述】:

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

系统时间更改可能有多种原因:

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

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

目标是检测是否发生了时移并平滑地校正我们的本地时间(例如,如果我们有一个一小时的“时间跳跃”,则每秒校正 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");
    

但是在进行一些测试时,我注意到即使在本地时间没有做任何事情,我也有差异。差别不大(

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):

    为什么两个Utc.DateTime 给了我这么大的差异?它们都基于时钟 Tick no? 难道没有办法更精确地得到这个时间偏移吗?

【问题讨论】:

【参考方案1】:

    不,它们不是都基于时钟滴答。 Stopwatch 可能是高分辨率或低分辨率。如果分辨率低,则使用DateTime.UtcNow underneith。不幸的是,你无法选择它是高还是低,所以:

    创建自己的“秒表”,始终使用DateTime.UtcNow underneith。

编辑

这是 (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 无论如何都适用于系统范围,所以请自己编写。

【讨论】:

我检查了,StopWatch.IsHighResolutionTrue,这使我可以在 DateTime.UtcNow 和使用秒表的时间测量之间有一个小的差异。但这种差异是预期的吗? 是的。据我了解,DateTime.UtcNow 正在查询您 PC 上的时钟,QueryPerformanceCounter 正在查询处理器。虽然还没有任何证据... 这可能会回答它connect.microsoft.com/VisualStudio/feedback/details/622002/… 通过谷歌搜索发现“Datetime vs QueryPerformanceCounter”可能是更好的信息。

以上是关于准确的时间追踪方法的主要内容,如果未能解决你的问题,请参考以下文章

需要眼动追踪,注视追踪方法

群发邮件追踪

追踪路由的2种方法

KCF追踪方法流程原理

追踪 Objective-C 方法中的 Block 参数对象

UE5中启用Lumen全局光照的方法