一尘不染

如何获取.NET / C#中的滴答精度时间戳?

c#

到目前为止,我一直使用DateTime.Now时间戳记,但是我注意到,如果您DateTime.Now循环打印,您会发现它以大约5%的离散跳跃递增。15毫秒
但是对于我的应用程序中的某些情况,我需要获得最准确的时间戳,最好是滴答(= 100 ns)精度。有任何想法吗?

更新:

显然,StopWatch/
QueryPerformanceCounter是要走的路,但是它只能用于测量时间,因此我在考虑DateTime.Now在应用程序启动时调用,然后才StopWatch运行,然后将经过的时间从添加到从StopWatch返回的初始值中DateTime.Now。至少那应该给我准确的相对时间戳,对吗?您如何看待(黑客)?

注意:

StopWatch.ElapsedTicks不同于StopWatch.Elapsed.Ticks!我使用前者假设1 tick = 100
ns,但在这种情况下1 tick = 1 /
StopWatch.Frequency。因此,要获取等于DateTime的报价,请使用StopWatch.Elapsed.Ticks。我只是很难学到的。

笔记2:

使用StopWatch方法,我注意到它与实时不同步。大约10个小时后,它领先了5秒钟。因此,我想每个X都必须重新同步一次,其中X可能是1小时,30分钟,15分钟等。我不确定重新同步的最佳时间间隔是多少,因为每次重新同步都会改变偏移量,长达20毫秒。


阅读 421

收藏
2020-05-19

共1个答案

一尘不染

DateTime.Now读取的系统时钟值仅每15毫秒左右(在某些系统上为10毫秒)更新一次,这就是为什么在这些间隔附近对时间进行量化的原因。由于您的代码在多线程OS中运行,因此还会产生额外的量化影响,因此在某些情况下,您的应用程序没有处于“活动”状态,因此无法测量实际的当前时间。

由于您正在寻找超准确的时间戳值(而不是仅计时任意持续时间),因此Stopwatch该类本身将无法满足您的需求。我认为您必须自己通过某种DateTime/
Stopwatch混合方式来做到这一点。当您的应用程序启动时,您将存储当前DateTime.UtcNow值(即,应用程序启动时的原始分辨率时间),然后还启动一个Stopwatch对象,如下所示:

DateTime _starttime = DateTime.UtcNow;
Stopwatch _stopwatch = Stopwatch.StartNew();

然后,每当您需要高分辨率DateTime值时,都将得到如下所示的结果:

DateTime highresDT = _starttime.AddTicks(_stopwatch.Elapsed.Ticks);

您可能还需要定期重置_starttime和_stopwatch,以防止产生的时间与系统时间过于不同步(尽管我不确定这是否会发生,并且无论如何都要花很长时间)

更新 :由于秒表 似乎确实 与系统时间
同步(每小时多达半秒),因此我认为DateTime根据两次调用检查之间经过的时间重置混合类是有意义的时间:

public class HiResDateTime
{
    private static DateTime _startTime;
    private static Stopwatch _stopWatch = null;
    private static TimeSpan _maxIdle = 
        TimeSpan.FromSeconds(10);

    public static DateTime UtcNow
    {
        get
        {
            if ((_stopWatch == null) || 
                (_startTime.Add(_maxIdle) < DateTime.UtcNow))
            {
                Reset();
            }
            return _startTime.AddTicks(_stopWatch.Elapsed.Ticks);
        }
    }

    private static void Reset()
    {
        _startTime = DateTime.UtcNow;
        _stopWatch = Stopwatch.StartNew();
    }
}

如果以某个固定间隔(例如每小时或某时)重置混合计时器,则冒着将时间设置为最后一次读取时间之前的风险,这有点像微型夏令时问题。

2020-05-19