C# Environment.TickCount 与 DateTime.Now
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/243351/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Environment.TickCount vs DateTime.Now
提问by Jon B
Is it ever OK to use Environment.TickCount
to calculate time spans?
可以Environment.TickCount
用来计算时间跨度吗?
int start = Environment.TickCount;
// Do stuff
int duration = Environment.TickCount - start;
Console.WriteLine("That took " + duration " ms");
Because TickCount
is signed and will rollover after 25 days (it takes 50 days to hit all 32 bits, but you have to scrap the signed bit if you want to make any sense of the math), it seems like it's too risky to be useful.
因为TickCount
已签名并将在 25 天后翻转(达到所有 32 位需要 50 天,但如果您想了解数学知识,则必须废弃签名位),所以似乎风险太大而无用。
I'm using DateTime.Now
instead. Is this the best way to do this?
我在用DateTime.Now
。这是最好的方法吗?
DateTime start = DateTime.Now;
// Do stuff
TimeSpan duration = DateTime.Now - start;
Console.WriteLine("That took " + duration.TotalMilliseconds + " ms");
采纳答案by Grzenio
Use Stopwatch class. There is a decent example on msdn: http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx
使用秒表类。msdn 上有一个不错的例子:http: //msdn.microsoft.com/en-us/library/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;
回答by Joel Coehoorn
You probably want System.Diagnostics.StopWatch
.
回答by Martin Kool
Use
用
System.Diagnostics.Stopwatch
It has a property called
它有一个属性叫做
EllapsedMilliseconds
回答by MusiGenesis
I use Environment.TickCount because:
我使用 Environment.TickCount 是因为:
- The Stopwatch class is not in the Compact Framework.
- Stopwatch uses the same underlying timing mechanism as TickCount, so the results won't be any more or less accurate.
- The wrap-around problem with TickCount is cosmically unlikely to be hit(you'd have to leave your computer running for 27 days and then try to measure a time that just happens to span the wrap-around moment), and even if you did hit it the result would be a huge negative time span (so it would kind of stand out).
- 秒表类不在 Compact Framework 中。
- 秒表使用与 TickCount 相同的底层计时机制,因此结果不会或多或少准确。
- TickCount 的环绕问题在宇宙中不太可能被击中(你必须让你的计算机运行 27 天,然后尝试测量恰好跨越环绕时刻的时间),即使你做到了击中它,结果将是一个巨大的负时间跨度(所以它会有点突出)。
That being said, I would also recommend using Stopwatch, if it's available to you. Or you could take about 1 minute and write a Stopwatch-like class that wraps Environment.TickCount.
话虽如此,如果您可以使用秒表,我也建议您使用它。或者,您可以花大约 1 分钟时间编写一个类似于秒表的类来封装 Environment.TickCount。
BTW, I see nothing in the Stopwatch documentation that mentions the wrap-around problem with the underlying timer mechanism, so I wouldn't be surprised at all to find that Stopwatch suffers from the same problem. But again, I wouldn't spend any time worrying about it.
顺便说一句,我在秒表文档中没有看到任何提到底层计时器机制的环绕问题的内容,所以发现秒表遇到同样的问题我一点也不感到惊讶。但同样,我不会花任何时间担心它。
回答by dongilmore
I was going to say wrap it into a stopwatch class, but Grzenio already said the right thing, so I will give him an uptick. Such encapsulation factors out the decision as to which way is better, and this can change in time. I remember being shocked at how expensive it can be getting the time on some systems, so having one place that can implement the best technique can be very important.
我本来想说把它打包成秒表课,但 Grzenio 已经说对了,所以我会给他加分。这种封装因素决定了哪种方式更好,并且这会随着时间而改变。我记得对在某些系统上花费时间的成本感到震惊,因此拥有一个可以实施最佳技术的地方可能非常重要。
回答by vanmelle
For one-shot timing, it's even simpler to write
对于一次性计时,写起来更简单
Stopwatch stopWatch = Stopwatch.StartNew();
...dostuff...
Debug.WriteLine(String.Format("It took {0} milliseconds",
stopWatch.EllapsedMilliseconds)));
I'd guess the cosmically unlikely wraparound in TickCount is even less of a concern for StopWatch, given that the ElapsedTicks field is a long. On my machine, StopWatch is high resolution, at 2.4e9 ticks per second. Even at that rate, it would take over 121 years to overflow the ticks field. Of course, I don't know what's going on under the covers, so take that with a grain of salt. However, I notice that the documentation for StopWatch doesn't even mention the wraparound issue, while the doc for TickCount does.
考虑到 ElapsedTicks 字段很长,我猜想在 TickCount 中不太可能出现的回绕对于 StopWatch 来说甚至更不用担心。在我的机器上,秒表是高分辨率的,每秒 2.4e9 个滴答声。即使按照这个速度,也需要超过 121 年的时间才能使刻度字段溢出。当然,我不知道幕后发生了什么,所以请谨慎对待。但是,我注意到 StopWatch 的文档甚至没有提到环绕问题,而 TickCount 的文档却提到了。
回答by vanmelle
Why are you worried about rollover? As long as the duration you are measuring is under 24.9 days and you calculate the relativeduration, you're fine. It doesn't matter how long the system has been running, as long as you only concern yourself with your portion of that running time (as opposed to directly performing less-than or greater-than comparisons on the begin and end points). I.e. this:
你为什么担心翻车?只要您测量的持续时间低于 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());
correctly prints:
正确打印:
before_rollover: 2147483642
after_rollover: -2147483641
duration: 13
You don't have to worry about the sign bit. C#, like C, lets the CPU handle this.
您不必担心符号位。C# 和 C 一样,让 CPU 处理这个问题。
This is a common situation I've run into before with time counts in embedded systems. I would never compare beforerollover < afterrollover directly, for instance. I would always perform the subtraction to find the duration that takes rollover into account, and then base any other calculations on the duration.
这是我之前在嵌入式系统中遇到时间计数的常见情况。例如,我永远不会直接比较 beforerollover < afterrollover。我将始终执行减法以找到将翻转考虑在内的持续时间,然后根据持续时间进行任何其他计算。
回答by Mark
If you're looking for the functionality of Environment.TickCount
but without the overhead of creating new Stopwatch
objects, you can use the static Stopwatch.GetTimestamp()
method (along with Stopwatch.Frequency
) to calculate long time spans. Because GetTimestamp()
returns a long
, it won't overflow for a very, very long time (over 100,000 years, on the machine I'm using to write this). It's also much more accurate than Environment.TickCount
which has a maximum resolution of 10 to 16 milliseconds.
如果您正在寻找 的功能Environment.TickCount
但没有创建新Stopwatch
对象的开销,您可以使用静态Stopwatch.GetTimestamp()
方法(连同Stopwatch.Frequency
)来计算长时间跨度。因为GetTimestamp()
返回 a long
,它不会在很长一段时间内溢出(超过 100,000 年,在我用来写这个的机器上)。它也比Environment.TickCount
最大分辨率为 10 到 16 毫秒的要准确得多。
回答by mistika
Environment.TickCountis based on GetTickCount()WinAPI function. It's in milliseconds But the actual precision of it is about 15.6 ms. So you can't measure shorter time intervals (or you'll get 0)
Environment.TickCount基于GetTickCount()WinAPI 函数。它以毫秒为单位,但它的实际精度约为 15.6 毫秒。所以你不能测量更短的时间间隔(否则你会得到 0)
Note:The returned value is Int32, so this counter rolls over each ~49.7 days. You shouldn't use it to measure such long intervals.
注意:返回的值为 Int32,因此此计数器每约 49.7 天滚动一次。你不应该用它来测量这么长的间隔。
DateTime.Ticksis based on GetSystemTimeAsFileTime() WinAPI function. It's in 100s nanoseconds (tenths of microsoconds). The actual precision of DateTime.Ticks depends on the system. On XP, the increment of system clock is about 15.6 ms, the same as in Environment.TickCount. On Windows 7 its precision is 1 ms (while Environemnt.TickCount's is still 15.6 ms), however if a power saving scheme is used (usually on laptops) it can go down to 15.6 ms as well.
DateTime.Ticks基于GetSystemTimeAsFileTime() WinAPI 函数。它以 100 纳秒(十分之一微秒)为单位。DateTime.Ticks 的实际精度取决于系统。XP系统时钟的增量约为15.6 ms,与Environment.TickCount中的相同。在 Windows 7 上,它的精度是 1 毫秒(而 Environemnt.TickCount 的精度仍然是 15.6 毫秒),但是如果使用节能方案(通常在笔记本电脑上),它也可以下降到 15.6 毫秒。
Stopwatchis based on QueryPerformanceCounter()WinAPI function (but if high-resolution performance counter is not supported by your system, DateTime.Ticks is used)
秒表基于QueryPerformanceCounter()WinAPI 函数(但如果您的系统不支持高分辨率性能计数器,则使用 DateTime.Ticks)
Before using StopWatch notice two problems:
使用秒表前注意两个问题:
- it can be unreliable on multiprocessor systems (see MS kb895980, kb896256)
- it can be unreliable if CPU frequency varies (read thisarticle)
You can evaluate the precision on your system with simple test:
您可以通过简单的测试来评估系统的精度:
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();
}