请善待,我只是学习C#并从前员工继承这个应用程序是我的第一个C#项目。
我正在使用System.Windows.Forms.Timer观察不一致和缓慢的时段。该应用程序是用C#与MS Visual Studio编写的。
定时器设置为100毫秒的间隔,但我观察的时间范围为110毫秒到180毫秒。
我正在使用几种工具来观察这一点,包括: - SW示波器(Iocomp.Instrumentation.Plotting.Plot包), - 一个真正的示波器, - 让计时器运行一段时间,并将滴答数* 100毫秒与系统时间和秒表进行比较。
在所有情况下,我观察到在最初的几秒钟内变得明显的10%滞后。
每个tick执行的方法运行时间不到4毫秒。也没有耗时的异步处理。但这应该无关紧要,因为计时器滴答是一个中断,而不是添加到事件处理程序队列的事件(据我所知)。
之前有没有人遇到这样的问题?根本原因是什么?
感谢。
答案 0 :(得分:7)
定时器仅与操作系统时钟中断一样准确。默认为每秒64次,15.625毫秒。你不能从那里获得一个干净的100毫秒间隔,它不能被15.625整除。你得到下一个整数倍,7 x 15.625 = 109.375毫秒。非常接近你观察到的110毫秒。
您需要将处理定时器通知的延迟添加到此理论最小值。计时器必须与UI线程中发生的所有其他事件竞争。它们被视为要发送的最少重要通知。首先发送消息,接下来是用户输入,接下来是绘画,定时消息是最后一个。无论哪种方式,如果你有一个精心设计的用户界面,需要一段时间来重新绘制,那么Tick事件将会延迟,直到完成。对于您编写的任何事件处理程序都是一样的,它可以执行诸如读取文件或查询dbase等非常重要的事情。
要获得一个不受此类延迟影响的响应更快的计时器,您需要使用异步计时器。 System.Threading.Timer或System.Timers.Timer。避免后者。它们的回调在线程池线程上运行,因此可以很快运行。你要非常小心你在这个回调中做了什么,因为它们不是线程安全的,所以你做不了很多事情。
通过更改时钟中断率,您可以更准确地定位这些定时器。这需要pinvoke,调用timeBeginPeriod()。完成后的timeEndPeriod()。
答案 1 :(得分:1)
是的,我总是在System.Windows.Forms.Timer
遇到这个问题,因为它没有准确(大部分时间)。
您可以尝试使用System.Timers.Timer
,它会精确地提高中断(至少精度为100ms)
答案 2 :(得分:0)
System.Windows.Forms.Timer
实际上只是本地WM_TIMER
消息的包装器。这意味着计时器消息在大致接近您请求的时间间隔时放置在消息队列中(加或减......这里不保证)。 处理该消息时,完全依赖于队列中的其他消息以及每个消息处理的时间。例如,如果阻止UI线程(从而阻止队列处理新消息),则在解除阻塞之前,您将无法获得计时器事件。
Windows不是实时操作系统,您不能期望定时器具有细粒度的准确性。如果你想要更细粒度的东西,多媒体计时器是最好的选择。
答案 3 :(得分:0)
这是旧的,但如果有人来这里寻找一个真正正确的答案:
来自https://msdn.microsoft.com/en-us/library/system.windows.forms.timer(v=vs.110).aspx(强调我的):
Windows窗体计时器组件是单线程的,并且限制为精度为55毫秒。如果需要更高精度的多线程计时器,请使用System.Timers命名空间中的Timer类。
因此,使用Windows.Forms.Timer,您可以获得55ms,110ms,165ms等;这与你所看到的一致。如果您需要更高的精确度,请尝试System.Timers.Timer
或System.Threading.Timer