【发布时间】:2013-03-10 12:18:00
【问题描述】:
我有一个创建新计时器的类,并在每次滴答时轮询远程队列(通过 HTTP)。
public void Start()
{
_timer = new Timer((x) =>
{
Console.WriteLine(DateTime.Now.ToString("hh:MM:ss.fff") + " " + typeof(T).Name);
var message = (Message)null;
var messageBody = (T)null;
try
{
if (!_queue.TryGet(out message))
return;
messageBody = (T)JsonConvert.DeserializeObject(message.Body, typeof(T));
_messageDispatcher.Dispatch<T>(messageBody);
_queue.Delete(message.Id);
}
catch (Exception ex)
{
_errorHandler.Handle(ex, message);
}
}, null, 0, _queueConsumerConfiguration.PollingInterval);
}
}
如果我创建这个类的八个新实例,将轮询间隔设置为 250 毫秒,然后调用它们,我会假设计时器会非常准确地计时。计时器回调中执行的内容无关紧要。然而事实并非如此。
01:03:23.305 MessageSleepForOneSecond
01:03:23.301 MessageSleepForOneSecond
01:03:23.297 MessageSleepForOneSecond
01:03:23.316 MessageSleepForOneSecond
01:03:24.321 MessageSleepForOneSecond
01:03:24.562 MessageSleepForOneSecond
01:03:24.701 MessageSleepForOneSecond
01:03:24.707 MessageSleepForOneSecond
01:03:24.716 MessageSleepForOneSecond
01:03:25.321 MessageSleepForOneSecond
01:03:25.518 MessageSleepForOneSecond
01:03:25.764 MessageSleepForOneSecond
01:03:25.912 MessageSleepForOneSecond
01:03:25.920 MessageSleepForOneSecond
01:03:25.924 MessageSleepForOneSecond
01:03:26.521 MessageSleepForOneSecond
01:03:26.710 MessageSleepForOneSecond
01:03:26.957 MessageSleepForOneSecond
01:03:27.107 MessageSleepForOneSecond
01:03:27.120 MessageSleepForOneSecond
01:03:27.126 MessageSleepForOneSecond
01:03:27.716 MessageSleepForOneSecond
01:03:27.906 MessageSleepForOneSecond
01:03:28.151 MessageSleepForOneSecond
01:03:28.305 MessageSleepForOneSecond
01:03:28.316 MessageSleepForOneSecond
01:03:28.322 MessageSleepForOneSecond
01:03:28.913 MessageSleepForOneSecond
01:03:29.100 MessageSleepForOneSecond
01:03:29.349 MessageSleepForOneSecond
01:03:29.502 MessageSleepForOneSecond
01:03:29.513 MessageSleepForOneSecond
01:03:29.538 MessageSleepForOneSecond
01:03:30.107 MessageSleepForOneSecond
01:03:30.297 MessageSleepForOneSecond
01:03:30.545 MessageSleepForOneSecond
01:03:30.705 MessageSleepForOneSecond
01:03:30.712 MessageSleepForOneSecond
01:03:30.733 MessageSleepForOneSecond
01:03:31.307 MessageSleepForOneSecond
01:03:31.310 MessageSleepForOneSecond
...
发生了什么事?是什么导致不准确? ThreadPool、Windows、...的管理?
【问题讨论】:
-
“我认为计时器会非常准确地计时” 为什么? Windows 不是实时操作系统。您的代码与大量其他代码共享处理器时间。
-
为了获得更高的准确性,让计时器每毫秒运行一次,并仅在达到间隔时计算自己执行的经过时间。
-
@CodyGray 没错,我的假设是错误的。但是什么是解释它的好方法? Windows 花费了太多时间来切换上下文,以至于不可能准确?
-
为什么“定时器回调中执行的内容”无关紧要?每个班级只有一个计时器。如果 HTTP 通信花费的时间长于计时器间隔,则计时器无法按时触发。
-
我不知道为什么这个问题被关闭为“没有建设性”,所以我投票重新打开它。 这绝对是一个可以用事实和参考来专业回答的问题。事实上,在这方面它已经得到了很好的回答。我不明白为什么人们认为“这个问题可能会引发辩论、争论、投票或扩展讨论”。尤其是鉴于杰夫的最后评论:“我想知道什么是解释为什么会发生的好方法。”也许这应该在问题本身中更加清楚......
标签: c# .net windows multithreading timer