到目前为止,我用于DateTime.Now
获取时间戳,但我注意到,如果DateTime.Now
在一个循环中打印,会看到它在不连续跳跃时增加约。15毫秒。但是对于我的应用程序中的某些场景,我需要获得最准确的时间戳,最好使用tick(= 100 ns)精度。有任何想法吗?
更新:
显然,StopWatch
/ QueryPerformanceCounter
是要走的路,但它只能用于测量时间,所以我在考虑调用DateTime.Now
应用程序何时启动,然后只是StopWatch
运行,然后将经过的时间添加StopWatch
到返回的初始值DateTime.Now
。至少应该给我准确的相对时间戳,对吗?你怎么看待这个?
注意:
StopWatch.ElapsedTicks
不同于StopWatch.Elapsed.Ticks
!我用前者假设1个tick = 100ns,但在这种情况下1个tick = 1 / StopWatch.Frequency
。所以得到相当于DateTime使用的滴答StopWatch.Elapsed.Ticks
。我刚刚学会了这个难题。
笔记2:
使用StopWatch方法,我发现它与实时不同步。大约10个小时后,它超前了5秒。所以我想我们不得不重新同步它每隔X左右,其中X可能是1小时,30分钟,15分钟等我不确定什么是最佳时间再同步将是因为每个resync会改变偏移量可以是最多20毫秒。
发布于 2018-03-19 11:12:52
DateTime.Now
读取的系统时钟值每15 ms左右更新一次(或在某些系统上为10 ms),这就是为什么时间量化在这些时间间隔周围的原因。由于代码运行在多线程操作系统中,因此会产生额外的量化效应,因此应用程序并不处于“活动状态”,因此无法测量实际当前时间。
既然你正在寻找一个超精确的时间标记值(而不是仅仅计算一个任意的持续时间),那么这个Stopwatch
类本身就不会满足你所需要的。我认为你必须自己做一个DateTime
/ Stopwatch
混合动力。当应用程序启动时,将存储当前DateTime.UtcNow
值(即应用程序启动时的原始分辨率时间),然后启动一个Stopwatch
对象,如下所示:
DateTime _starttime = DateTime.UtcNow;
Stopwatch _stopwatch = Stopwatch.StartNew();
然后,每当你需要一个高分辨率的DateTime
值时,你会得到这样的结果:
DateTime highresDT = _starttime.AddTicks(_stopwatch.Elapsed.Ticks);
还可能需要定期重置_starttime和_stopwatch,以避免产生的时间与系统时间过度不同步(尽管我不确定这是否会发生,而且无论如何都需要很长时间才会发生) 。
由于看起来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();
}
}
如果以某个固定时间间隔(例如每小时或某些时间)重置混合计时器,则会有在上次读取时间之前设置时间的风险,这就像微型夏令时问题。
发布于 2018-03-19 12:35:53
如果你真正关心的实际上是一个独特的时间戳,它是按严格升序排列的,并且尽可能接近系统时间,你可以尝试这种替代方法:
public class HiResDateTime
{
private static long lastTimeStamp = DateTime.UtcNow.Ticks;
public static long UtcNowTicks
{
get
{
long orig, newval;
do
{
orig = lastTimeStamp;
long now = DateTime.UtcNow.Ticks;
newval = Math.Max(now, orig + 1);
} while (Interlocked.CompareExchange
(ref lastTimeStamp, newval, orig) != orig);
return newval;
}
}
}
https://stackoverflow.com/questions/-100003196
复制相似问题