到目前为止,我一直使用DateTime.Now时间戳记,但是我注意到,如果您DateTime.Now循环打印,您会发现它以大约5%的离散跳跃递增。15毫秒 但是对于我的应用程序中的某些情况,我需要获得最准确的时间戳,最好是滴答(= 100 ns)精度。有任何想法吗?
DateTime.Now
更新:
显然,StopWatch/ QueryPerformanceCounter是要走的路,但是它只能用于测量时间,因此我在考虑DateTime.Now在应用程序启动时调用,然后才StopWatch运行,然后将经过的时间从添加到从StopWatch返回的初始值中DateTime.Now。至少那应该给我准确的相对时间戳,对吗?您如何看待(黑客)?
StopWatch
QueryPerformanceCounter
注意:
StopWatch.ElapsedTicks不同于StopWatch.Elapsed.Ticks!我使用前者假设1 tick = 100 ns,但在这种情况下1 tick = 1 / StopWatch.Frequency。因此,要获取等于DateTime的报价,请使用StopWatch.Elapsed.Ticks。我只是很难学到的。
StopWatch.ElapsedTicks
StopWatch.Elapsed.Ticks
StopWatch.Frequency
笔记2:
使用StopWatch方法,我注意到它与实时不同步。大约10个小时后,它领先了5秒钟。因此,我想每个X都必须重新同步一次,其中X可能是1小时,30分钟,15分钟等。我不确定重新同步的最佳时间间隔是多少,因为每次重新同步都会改变偏移量,长达20毫秒。
DateTime.Now读取的系统时钟值仅每15毫秒左右(在某些系统上为10毫秒)更新一次,这就是为什么在这些间隔附近对时间进行量化的原因。由于您的代码在多线程OS中运行,因此还会产生额外的量化影响,因此在某些情况下,您的应用程序没有处于“活动”状态,因此无法测量实际的当前时间。
由于您正在寻找超准确的时间戳值(而不是仅计时任意持续时间),因此Stopwatch该类本身将无法满足您的需求。我认为您必须自己通过某种DateTime/ Stopwatch混合方式来做到这一点。当您的应用程序启动时,您将存储当前DateTime.UtcNow值(即,应用程序启动时的原始分辨率时间),然后还启动一个Stopwatch对象,如下所示:
Stopwatch
DateTime
DateTime.UtcNow
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(); } }
如果以某个固定间隔(例如每小时或某时)重置混合计时器,则冒着将时间设置为最后一次读取时间之前的风险,这有点像微型夏令时问题。