如何在 .NET/C# 中获取刻度精度的时间戳? [英] How to get timestamp of tick precision in .NET / C#?

查看:21
本文介绍了如何在 .NET/C# 中获取刻度精度的时间戳?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

到目前为止,我使用 DateTime.Now 来获取时间戳,但我注意到,如果您在循环中打印 DateTime.Now,您会看到它逐渐递增跳跃约.15 毫秒.但是对于我的应用程序中的某些场景,我需要尽可能获得最准确的时间戳,最好是刻度(= 100 ns)精度.有任何想法吗?

Up until now I used DateTime.Now for getting timestamps, but I noticed that if you print DateTime.Now in a loop you will see that it increments in descrete jumps of approx. 15 ms. But for certain scenarios in my application I need to get the most accurate timestamp possible, preferably with tick (=100 ns) precision. Any ideas?

更新:

显然, StopWatch/QueryPerformanceCounter 是要走的路,但它只能用来测量时间,所以我在考虑调用 DateTime.Now 当应用程序启动,然后运行 ​​StopWatch 然后将 StopWatch 的经过时间添加到 DateTime.Now 返回的初始值.至少这应该给我准确的相对时间戳,对吧?你怎么看这个(黑客)?

Apparently, StopWatch / QueryPerformanceCounter is the way to go, but it can only be used to measure time, so I was thinking about calling DateTime.Now when the application starts up and then just have StopWatch run and then just add the elapsed time from StopWatch to the initial value returned from DateTime.Now. At least that should give me accurate relative timestamps, right? What do you think about that (hack)?

注意:

StopWatch.ElapsedTicksStopWatch.Elapsed.Ticks 不同!我使用前者,假设 1 tick = 100 ns,但在本例中 1 tick = 1/StopWatch.Frequency.因此,要获得与 DateTime 等效的刻度,请使用 StopWatch.Elapsed.Ticks.我刚刚学会了这一点.

StopWatch.ElapsedTicks is different from StopWatch.Elapsed.Ticks! I used the former assuming 1 tick = 100 ns, but in this case 1 tick = 1 / StopWatch.Frequency. So to get ticks equivalent to DateTime use StopWatch.Elapsed.Ticks. I just learned this the hard way.

注意 2:

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

Using the StopWatch approach, I noticed it gets out of sync with the real time. After about 10 hours, it was ahead by 5 seconds. So I guess one would have to resync it every X or so where X could be 1 hour, 30 min, 15 min, etc. I am not sure what the optimal timespan for resyncing would be since every resync will change the offset which can be up to 20 ms.

推荐答案

DateTime.Now 读取的系统时钟值仅每 15 毫秒左右更新一次(在某些系统上为 10 毫秒)),这就是为什么围绕这些间隔量化时间的原因.由于您的代码在多线程操作系统中运行,因此会产生额外的量化效果,因此在某些情况下您的应用程序不活跃",因此无法测量实际的当前时间.

The value of the system clock that DateTime.Now reads is only updated every 15 ms or so (or 10 ms on some systems), which is why the times are quantized around those intervals. There is an additional quantization effect that results from the fact that your code is running in a multithreaded OS, and thus there are stretches where your application is not "alive" and is thus not measuring the real current time.

由于您正在寻找一个超精确的时间戳值(而不是仅仅计时任意持续时间),Stopwatch 类本身不会满足您的需求.我认为您必须自己使用一种 DateTime/Stopwatch 混合来执行此操作.当您的应用程序启动时,您将存储当前的 DateTime.UtcNow 值(即应用程序启动时的粗分辨率时间),然后还启动一个 Stopwatch 对象,如下所示:

Since you're looking for an ultra-accurate time stamp value (as opposed to just timing an arbitrary duration), the Stopwatch class by itself will not do what you need. I think you would have to do this yourself with a sort of DateTime/Stopwatch hybrid. When your application starts, you would store the current DateTime.UtcNow value (i.e. the crude-resolution time when your application starts) and then also start a Stopwatch object, like this:

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

然后,当您需要一个高分辨率的 DateTime 值时,您会得到这样的:

Then, whenever you need a high-resolution DateTime value, you would get it like this:

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

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

You also may want to periodically reset _starttime and _stopwatch, to keep the resulting time from getting too far out of sync with the system time (although I'm not sure this would actually happen, and it would take a long time to happen anyway).

更新:因为看起来秒表确实与系统时间不同步(最多每小时半秒),我认为这是有道理的根据调用之间经过的时间来重置混合 DateTime 类以检查时间:

Update: since it appears that Stopwatch does get out of sync with the system time (by as much as half a second per hour), I think it makes sense to reset the hybrid DateTime class based on the amount of time that passes between calls to check the time:

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();
    }
}

如果您以某个固定的时间间隔(比如每小时或其他时间)重置混合计时器,您可能会将时间设置回上次读取时间之前,这有点像一个微型夏令时问题.

If you reset the hybrid timer at some regular interval (say every hour or something), you run the risk of setting the time back before the last read time, kind of like a miniature Daylight Savings Time problem.

这篇关于如何在 .NET/C# 中获取刻度精度的时间戳?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆