可以使用吗 Environment.TickCount计算时间跨度?

int start = Environment.TickCount;
// Do stuff
int duration = Environment.TickCount - start;
Console.WriteLine("That took " + duration " ms");

因为 TickCount 已签名,并将在 25 天后滚动(需要 50 天才能达到所有 32 位,但如果您想了解数学意义,则必须废弃已签名的位),似乎风险太大而无用。

我在用着 DateTime.Now 反而。这是最好的方法吗?

DateTime start = DateTime.Now;
// Do stuff
TimeSpan duration = DateTime.Now - start;
Console.WriteLine("That took " + duration.TotalMilliseconds + " ms");
有帮助吗?

解决方案

使用秒表课程。在msdn上有一个不错的例子: http://msdn.microsoft的.com / EN-US /库/ system.diagnostics.stopwatch.aspx

    Stopwatch stopWatch = Stopwatch.StartNew();
    Thread.Sleep(10000);
    stopWatch.Stop();
    // Get the elapsed time as a TimeSpan value.
    TimeSpan ts = stopWatch.Elapsed;

其他提示

环境.TickCount 是基于 获取TickCount() WinAPI函数。它以毫秒为单位,但实际的精度约为15.6毫秒。所以你不能测量更短的时间间隔(否则你会得到0)

笔记: 返回的值为 Int32,因此该计数器每约 49.7 天滚动一次。您不应该用它来测量这么长的间隔。

日期时间.Ticks 是基于 获取系统时间作为文件时间()WinAPI 函数。它以 100 纳秒(十分之一微秒)为单位。DateTime.Ticks 的实际精度取决于系统。在XP上,系统时钟的增量约为15.6 ms,与Environment.TickCount中相同。在 Windows 7 上,其精度为 1 毫秒(而 Environemnt.TickCount 的精度仍为 15.6 毫秒),但是如果使用节能方案(通常在笔记本电脑上),它也可以降至 15.6 毫秒。

跑表 是基于 查询性能计数器() WinAPI函数(但如果您的系统不支持高分辨率性能计数器,则使用DateTime.Ticks)

使用秒表之前注意两个问题:

您可以通过简单的测试来评估系统的精度:

static void Main(string[] args)
{
    int xcnt = 0;
    long xdelta, xstart;
    xstart = DateTime.UtcNow.Ticks;
    do {
        xdelta = DateTime.UtcNow.Ticks - xstart;
        xcnt++;
    } while (xdelta == 0);

    Console.WriteLine("DateTime:\t{0} ms, in {1} cycles", xdelta / (10000.0), xcnt);

    int ycnt = 0, ystart;
    long ydelta;
    ystart = Environment.TickCount;
    do {
        ydelta = Environment.TickCount - ystart;
        ycnt++;
    } while (ydelta == 0);

    Console.WriteLine("Environment:\t{0} ms, in {1} cycles ", ydelta, ycnt);


    Stopwatch sw = new Stopwatch();
    int zcnt = 0;
    long zstart, zdelta;

    sw.Start();
    zstart = sw.ElapsedTicks; // This minimizes the difference (opposed to just using 0)
    do {
        zdelta = sw.ElapsedTicks - zstart;
        zcnt++;
    } while (zdelta == 0);
    sw.Stop();

    Console.WriteLine("StopWatch:\t{0} ms, in {1} cycles", (zdelta * 1000.0) / Stopwatch.Frequency, zcnt);
    Console.ReadKey();
}

你为什么担心翻车?只要您测量的持续时间低于24.9天并计算相对持续时间,您就可以了。系统运行的时间并不重要,只要您只关心自己运行时间的一部分(而不是直接执行小于或大于开始和结束点的比较)。即这样:

 int before_rollover = Int32.MaxValue - 5;
 int after_rollover = Int32.MinValue + 7;
 int duration = after_rollover - before_rollover;
 Console.WriteLine("before_rollover: " + before_rollover.ToString());
 Console.WriteLine("after_rollover: " + after_rollover.ToString());
 Console.WriteLine("duration: " + duration.ToString());

正确打印:

 before_rollover: 2147483642
 after_rollover: -2147483641
 duration: 13

您不必担心标志位。 C#和C一样,让CPU处理这个。

这是我在嵌入式系统中计算时间之前遇到的常见情况。我永远不会比较之前<!> lt;例如,直接后滚动。我总是会执行减法来找到考虑翻转的持续时间,然后根据持续时间进行任何其他计算。

您可能需要 System.Diagnostics.StopWatch

如果您正在寻找Environment.TickCount的功能但没有创建新Stopwatch对象的开销,则可以使用静态Stopwatch.GetTimestamp()方法(以及Stopwatch.Frequency)来计算长时间跨度。因为GetTimestamp()返回long,它不会在很长一段时间内溢出(超过10万年,在我用来编写它的机器上)。它也比<=>准确得多,其最大分辨率为10到16毫秒。

使用

System.Diagnostics.Stopwatch

它有一个名为

的属性
EllapsedMilliseconds

Environment.TickCount似乎比其他解决方案快得多:

Environment.TickCount 71
DateTime.UtcNow.Ticks 213
sw.ElapsedMilliseconds 1273

测量结果由以下代码生成:

static void Main( string[] args ) {
    const int max = 10000000;
    //
    //
    for ( int j = 0; j < 3; j++ ) {
        var sw = new Stopwatch();
        sw.Start();
        for ( int i = 0; i < max; i++ ) {
            var a = Environment.TickCount;
        }
        sw.Stop();
        Console.WriteLine( $"Environment.TickCount {sw.ElapsedMilliseconds}" );
        //
        //
        sw = new Stopwatch();
        sw.Start();
        for ( int i = 0; i < max; i++ ) {
            var a = DateTime.UtcNow.Ticks;
        }
        sw.Stop();
        Console.WriteLine( $"DateTime.UtcNow.Ticks {sw.ElapsedMilliseconds}" );
        //
        //
        sw = new Stopwatch();
        sw.Start();
        for ( int i = 0; i < max; i++ ) {
            var a = sw.ElapsedMilliseconds;
        }
        sw.Stop();
        Console.WriteLine( $"sw.ElapsedMilliseconds {sw.ElapsedMilliseconds}" );
    }
    Console.WriteLine( "Done" );
    Console.ReadKey();
}

这是一种更新的<!>放大器;更新了可能是最有用的答案的摘要<!> amp;此主题中的评论+额外的基准和变体:

首先要做的事情:正如其他人在评论中指出的那样,事情已经改变了过去的几年,并且用<!> quot; modern <!> Windows(Win XP ++)和.NET以及现代硬件没有或几乎没有理由不使用Stopwatch()。 请参阅

我使用Environment.TickCount,因为:

  1. Stopwatch类不在Compact Framework中。
  2. 秒表使用与TickCount相同的基础计时机制,因此结果不会更准确或更准确。
  3. TickCount的环绕问题在很大程度上不太可能被击中(您必须让计算机运行27天,然后尝试测量恰好跨越换行的时间(即时)),即使你确实击中了它,结果也会是一个巨大的负时间跨度(所以它会很突出)。
  4. 话虽如此,我还建议使用秒表,如果你可以使用的话。或者你可以花大约1分钟写一个类似秒表的类来包装Environment.TickCount。

    顺便说一句,我在秒表文档中没有看到提及底层计时器机制的环绕问题,所以我不会惊讶地发现秒表遇到了同样的问题。但同样,我也不会花时间担心它。

我打算把它包装成一个秒表课,但Grzenio已经说了正确的话,所以我会给他一个提升。这种封装因素决定了哪种方式更好,这可以及时改变。我记得对于在一些系统上花费多少时间感到震惊,因此拥有一个可以实现最佳技术的地方非常重要。

对于一次性定时,写入

更简单
Stopwatch stopWatch = Stopwatch.StartNew();
...dostuff...
Debug.WriteLine(String.Format("It took {0} milliseconds",
                              stopWatch.EllapsedMilliseconds)));

考虑到ElapsedTicks字段很长,我猜想TickCount中的宇宙不太可能的回绕甚至不太关注StopWatch。在我的机器上,StopWatch是高分辨率,每秒2.4e9滴答。即使按照这个速度,也需要超过121年的时间才能超过蜱虫领域。当然,我不知道封面下发生了什么,所以拿出一粒盐。但是,我注意到StopWatch的文档甚至没有提到回绕问题,而TickCount的文档也没有。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top