【发布时间】:2014-07-16 23:19:06
【问题描述】:
在经过时间测量期间偶然发现意外行为。
我从Stopwatch类开始:
for (int i = 0; i < 100; i++)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
Thread.Sleep(200);
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
}
https://dotnetfiddle.net/3hch1R
但事实证明,每隔一段时间,经过的时间会少于 200 毫秒。
然后是DateTime.Now 的时间,它也显示了一些奇怪的东西:
for (int i = 0; i < 100; i++)
{
var start = DateTime.Now.Millisecond;
Thread.Sleep(200);
var stop = DateTime.Now.Millisecond;
Console.WriteLine(stop - start);
}
https://dotnetfiddle.net/2vo2yw
像这样简单的事情通常会返回负面结果。
所以我的问题是:这两个班级出现这种行为的原因是什么?如何更准确地测量经过的时间(没有负偏差)?
有一个关于秒表的post 对这个话题有所启发,但那里的 cmets 看起来有点矛盾。
编辑1:
正如 AlexD 所发现的,DateTime.Now.Millisecond 只返回毫秒部分,而不是 TotalMilliseconds。所以这个很清楚。
编辑2:
根据建议,我决定使用 DateTime,它的结果满足我的精度要求:
for (int i = 0; i < 100; i++)
{
var start = (int)DateTime.UtcNow.TimeOfDay.TotalMilliseconds;
Thread.Sleep(200);
var stop = (int)DateTime.UtcNow.TimeOfDay.TotalMilliseconds;
Console.WriteLine(stop - start);
}
或者DateTime.UtcNow.Ticks / TimeSpan.TicksPerMillisecond,如果您需要在测量之间更改天数。
【问题讨论】:
-
Thread.Sleep 是出了名的不准确,请参阅stackoverflow.com/questions/12321225/…
-
@Alex 我最初使用了
System.Threading.Timer,它显示了相同的结果,所以为了节省空间,我决定在示例中使用Thread.Sleep -
相同的答案,请参见此处:stackoverflow.com/questions/3744032/…。我认为它只睡了大约 200 毫秒,这有时意味着更少。
-
我无法重现第一个问题。对我来说
stopwatch.ElapsedMilliseconds到目前为止返回值>= 200。 -
你想在哪里获得 200,400,600,...等等?