我的申请会收到客户的指示。
在每条指令上,我想从接收的时间戳+ 10秒执行代码。
为了测试我的代码的准确性,我模拟了这个简单的控制台测试:
static DateTime d1 = DateTime.Now;
static Timer _timer = null;
static void Main(string[] args)
{
_timer = new Timer(Callback, null,200, Timeout.Infinite);
d1 = DateTime.Now;
Console.ReadLine();
}
private static void Callback(Object state)
{
TimeSpan s = DateTime.Now - d1;
Console.WriteLine("Done, took {0} secs.", s.Milliseconds);
_timer.Change(200, Timeout.Infinite);
}
在运行它时我曾希望显示:
Done, took 200 milsecs.
Done, took 200 milsecs.
Done, took 200 milsecs.
Done, took 200 milsecs.
Done, took 200 milsecs.
Done, took 200 milsecs.
但事实并非如此。
我得到'milsecs'的随机值。
NB 我的实际代码并不总是使用200毫秒。
屏幕截图示例:
答案 0 :(得分:3)
首先,您使用TimeSpan.Milliseconds
属性,即int
并且只返回时间跨度的毫秒部分。为确保您获得全职,请使用TotalMilliseconds
其次,您没有在每个循环中重置d1
,因此您将看到总时间,而不是每次迭代的时间。要解决此问题,请务必在回调结束时设置d1 = DateTime.Now
,以便下一个循环使用正确的时间。
最后,由于线程,方法调用甚至是您正在进行的减法操作的开销,您可能会看到一定的差异,而不是完美的200ms间隔。此外,根据this article from Eric Lippert:
,DateTime
并不总是具有最高的准确性
如果你想问的问题是一些操作有多长 花了,你想要一个高精度,高精度的答案,然后使用 StopWatch班。
因此:
static Stopwatch _watch = Stopwatch.StartNew();
static Timer _timer = null;
static void Main(string[] args)
{
_timer = new Timer(Callback, null,200, Timeout.Infinite);
Console.ReadLine();
}
private static void Callback(Object state)
{
TimeSpan s = _watch.Elapsed;
_watch.Restart();
Console.WriteLine("Done, took {0} secs.", s.TotalMilliseconds);
_timer.Change(200, Timeout.Infinite);
}
答案 1 :(得分:1)
s.Milliseconds
可以说是小数点后的毫秒数。您需要TotalMilliseconds
。这些属性非常有名。它们是许多SO问题的原因。
内置定时器应该有大约15ms的分辨率(或者它的一小部分)并且可能有一些偏差(我不知道)。