请仁慈,我正在学习C#,从一个前雇员那里继承这个应用程序是我的第一个C#项目。
我在使用System.Windows.Forms.Timer时观察到不一致和缓慢的阶段。该应用程序是使用MS Visual Studio用C#编写的。
计时器设置为100毫秒的间隔,但我观察到的周期从110毫秒到180毫秒不等。
我正在使用几个工具来观察这一点,包括:-一个SW示波器( Iocomp.Instrumentation.Plotting.Plot软件包),-一个真正的示波器,-让计时器运行一段时间,并比较* 100毫秒与系统时间和秒表的滴答数。
在所有情况下,我都观察到了10%的滞后,这在最初的几秒钟内变得很明显。
每个节拍执行的方法运行所需的时间不到4毫秒。也不会发生耗时的异步处理。不过,这应该无关紧要,因为计时器滴答是一个中断,而不是添加到事件处理程序队列中的事件(据我所知)。
以前有没有人遇到过这样的问题?根本原因是什么?
谢谢。
发布于 2014-09-17 04:14:26
计时器只能与操作系统时钟中断一样精确。默认每秒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()。
发布于 2014-09-17 03:20:15
是的,我在使用System.Windows.Forms.Timer时总是遇到这个问题,因为它不能准确地计时(大多数时候)。你可以尝试System.Timers.Timer,它会精确地触发中断(至少100ms的精度)
发布于 2014-09-17 03:25:30
System.Windows.Forms.Timer实际上只是原生WM_TIMER消息的包装器。这意味着计时器消息放在消息队列中的时间大致接近您请求的时间间隔(加或减...这里没有保证)。处理该消息的时间完全取决于队列中的其他消息,以及每个消息需要多长时间才能处理。例如,如果阻塞UI线程(从而阻止队列处理新消息),则直到解除阻塞之后才会获得计时器事件。
Windows不是实时操作系统,你不能指望计时器有细粒度的精确度。如果你想要更细粒度的东西,多媒体定时器是最好的选择。
https://stackoverflow.com/questions/25876342
复制相似问题