如何提高图片精度TIMER的精度

如何在C#中实现精确timer? - 第1页 - 网络编程 - 速达社区 - 简约版
& 如何在C#中实现精确timer?
近来在做一个关于音乐合成的东西,其中需要较高的时间精度,利用timer,发现每10秒左右总会有毫秒级的误差…… 请问还有没有更精确一点的计时器? 希望各位能够贴上一段代码,帮我解决这个问题!谢谢!!
各位大哥大姐,拜托你们了!谢谢!!
System.Threading.Timer 比Timer控件精确!
计时器常用的只有Timer和线程了,不过平时没有考虑到误差的问题, 如果计时器不成你可以试下用线程来计时, & 不过估计也有误差的
用线程吧,用GetTickCount()判断时间差
秒不正确 就精确到 & 毫秒 & 微妙啊 直接用 & 毫秒 & 数值表示 & 不是更精确了...
关于C#中timer类 & & 在C#里关于定时器类就有3个 & & & 1.定义在System.Windows.Forms里 & & & 2.定义在System.Threading.Timer类里 & & & 3.定义在System.Timers.Timer类里 & & System.Windows.Forms.Timer是应用于WinForm中的,它是通过Windows消息机制实现的,类似于VB或Delphi中的Timer控件,内部使用API & & SetTimer实现的。它的主要缺点是计时不精确,而且必须有消息循环,Console & & Application(控制台应用程序)无法使用。 & & &
& &System.Timers.Timer和System.Threading.Timer非常类似,它们是通过.NET & & Thread & & Pool实现的,轻量,计时精确,对应用程序、消息没有特别的要求。System.Timers.Timer还可以应用于WinForm,完全取代上面的Timer控件。它们的缺点是不支持直接的拖放,需要手工编码。 & 例: & 使用System.Timers.Timer类 & System.Timers.Timer & t & = & new & System.Timers.Timer(10000);//实例化Timer类,设置间隔时间为10000毫秒; & t.Elapsed & += & new & System.Timers.ElapsedEventHandler(theout);//到达时间的时候执行事件; & t.AutoReset & = &//设置是执行一次(false)还是一直执行(true); & t.Enabled & = &//是否执行System.Timers.Timer.Elapsed事件; & public & void & theout(object & source, & System.Timers.ElapsedEventArgs & e) & { & MessageBox.Show( &OK! &); & } & & & 关于定时器 定时器是个很有意思的东西,它很有用,但我认为这不是现代计算机的结构所擅长的事情。 计算机适合做那些很大量的简单重复工作,或者根据请求做出回应。 DOS时代是没有进程线程等概念的,那时候要想做到定时真是有些麻烦 通常的做法是死循环不断监测时间,发现时间到了就做特定的事情 当然你可以用delay,来指定等待多长时间,但是如果你一边要响应用户的操作,比如输入,一边要定时做些 事情就是一件麻烦的事了 当然有些人可以这样做,截取系统的时钟中断(我忘了中断号是多少了),每秒钟有18.2次 当这些做法都不是很优雅。但DOS时代只能这样凑合着了 Windows是个伟大的进步,系统提供了Timer支持,但是问题是这个定时器并不准时而且有时候根本不能用。 Win32 & API中有个SetTimer函数,可以为一个窗口创建一个定时器,这个定时器会定时产生消息WM_TIMER也可以调用 指定的回调函数,其实这都是一样的,因为都是单线程的。 单线程的定时器会有很多问题,首先是不准时,定时器只是定时把消息WM_TIMER访到线程的消息队列里,但是并不保证消息会立刻被响应,如果 碰巧系统比较忙,那么消息可能会在队列里放一端时间才被响应,还会造成本来应该间隔一段时间发生的消息响应连续发生了 解决方法通常是 OnTimer(...) {
&//Timer & process.....
&While(PeekMessage(&msg, & m_hWnd, & WM_TIMER, & WM_TIMER, & PM_REMOVE)); } 在当前Timer处理中,把消息队列里的WM_TIMER消息,清除掉。 更糟的是如果你不去调用GetMessage,那么就不会有Timer发生了。 这个问题直到win & xp都没什么改变,似乎微软并不打算在Win32 & API中解决这个问题了。 .NET & Framework为我们带来了新的解决方案 .NET & Framework提供三种Timer Server & Timers & & & & & & & & System.Timers.Timer Thread & Timers & & & & & & & System.Threading.Timer & Windows & Timers & & & System.Windows.Forms.Timer 其中Windows & Timers只是提供了和WinAPI & 一样的Timer,仍然是基于消息,仍然是单线程 其它两个就不同了,他们是基于线程池的Thread & Pool,这样最大的好处在于,产生的时间间隔准确均匀。 Server & Timers & & 和 & Thread & Timers & 的不同在于ServerTimers & 是基于事件的,Thread & Timers是基于回调函数 我更喜欢Thread & Timer,比较轻量级方便易用。 但是这样的Timer也有问题,就是由于时多线程定时器,就会出现如果一个Timer处理没有完成,到了时间下一个 照样会发生,这就会导致重入问题 对付重入问题通常的办法是加锁,但是对于 & Timer却不能简单的这样做,你需要评估一下 首先Timer处理里本来就不应该做太需要时间的事情,或者花费时间无法估计的事情,比同远方的服务器建立一个网络连接,这样的做法尽量避免 如果实在无法避免,那么要评估Timer处理超时是否经常发生,如果是很少出现,那么可以用lock(Object)的方法来防止重入 如果这种情况经常出现呢?那就要用另外的方法来防止重入了 我们可以设置一个标志,表示一个Timer处理正在执行,下一个Timer发生的时候发现上一个没有执行完就放弃执行 static & & int & inTimer & = & 0; public & static & void & threadTimerCallback(Object & obj) {
& & & & &if & ( & inTiemr & == & 0 & )
& & & & & & & & &inTimer & = & 1; & & & & & & & & &
& & & & & & & & &Console.WriteLine( &Time:{0}, & \tThread & ID:{1} &, & DateTime.Now, & Thread.CurrentThread.GetHashCode());
& & & & & & & & &Thread.Sleep(2000);
& & & & & & & & &inTimer & = & 0;
& & & & & &} } 但是在多线程下给inTimer赋值不够安全,还好Interlocked.Exchange提供了一种轻量级的线程安全的给对象赋值的方法
&static & int & inTimer & = & 0;
&public & static & void & threadTimerCallback(Object & obj)
& & & & & & &if & ( & Interlocked.Exchange(ref & inTimer, & 1) & == & 0 & )
& & & & & &{
& & & & & & & & & & &Console.WriteLine( &Time:{0}, & \tThread & ID:{1} &, & DateTime.Now, & Thread.CurrentThread.GetHashCode());
& & & & & & & & & & &Thread.Sleep(250);
& & & & & & & & & & &Interlocked.Exchange(ref & inTimer, & 0);
& & & & & &}
&} 正确的选择使用.NET中的三个Timer & Timer这个类在.NET的类库中有三个: 1)System.Threading.Timer &
& & & & & &是一个使用回调方法的计时器,而且由线程池线程服务,简单且对资源要求不高。 2)System.Windows.Forms.Timer &
& & & & &这是一个必须和Windows窗体一起使用的Timer。 3)System.Timers.Timer
& & & & & &基于服务器计时器功能的Timer,根据服务器系统时间进行运行的Timer。如果需要写Windows & Services的话可以使用这个Timer来进行一 些需要在一定间隔时间进行某项操作的环境下使用。
& & & & & &它使您能够指定在应用程序中引发 & Elapsed & 事件的周期性间隔。然后可以操控此事件以提供定期处理。例如,假设您有一台关键性服务 器,必须每周 & 7 & 天、每天 & 24 & 小时都保持运行。可以创建一个使用 & Timer & 的服务,以定期检查服务器并确保系统开启并在运行。如果系统不 响应,则该服务可以尝试重新启动服务器或通知管理员。基于服务器的 & Timer & 是为在多线程环境中用于辅助线程而设计的。服务器计时器可 以在线程间移动来处理引发的 & Elapsed & 事件,这样就可以比 & Windows & 计时器更精确地按时引发事件。
我觉得可以自己做一个类似游戏中控制贞数的东西
API,取CPU频率
看能否找到更精确的控件,求三种Timer控件的区别?_服务器_百科问答
求三种Timer控件的区别?
提问者:叶千雨
1、 System.Windows.Form.Timer:基于UI层的计时器,与UI在同一个线程,在timer的事件处理中,UI层失去响应。单线程组件,精度限定为 55 毫秒。事件由Tick触发。2、 System.Timers.Timer:基于服务器的计时器,与UI不在同一个线程。多线程组件。Elapsed 事件在 ThreadPool 线程上引发。如果 Elapsed 事件的处理时间比 Interval 长,在另一个 ThreadPool 线程上将会再次引发此事件。因此,事件处理程序应当是可重入的。3、 System.Threading.Timer:基于线程的计时器,是一个简单的轻量计时器,使用 TimerCallback 委托指定希望 Timer 执行的方法,由计时器执行的回调方法应该是可重入的,因为它是在 ThreadPool ----------------------------------------------------------------------------- 基于服务器的计时器允许指定在应用程序中引发事件的重复时间间隔。然后可通过处理这个事件来提供常规处理。例如,假设您有一台关键的服务器,必须保持一周 7 天、一天 24 小时连续运行。您可以创建一个服务,通过使用计时器来定期检查关键的服务器,确保系统启动并运行。如果该系统没有响应,此服务可以尝试重新启动服务器或通知系统管理员。
注意 以毫秒为单位指定服务器计时器的时间间隔。
服务器计时器、Windows 计时器和线程计时器
在 Visual Studio .NET 和 .NET Framework 中有三种计时器控件:基于服务器的计时器,位于&工具箱&的&组件&选项卡上;基于 Windows 的标准计时器,位于&工具箱&的&Windows 窗体&选项卡上,以及仅可在编程时使用的线程计时器。基于 Windows 的计时器从 Visual Basic 的 1.0 版起就存在于该产品中并且基本上保持不变。该计时器已经为在 Windows 窗体应用程序中使用而进行了优化。基于服务器的计时器是传统的计时器为了在服务器环境上运行而优化后的更新版本。线程计时器是一种简单的、轻量级计时器,使用回调方法而不是事件,并由线程池线程提供。
在 Win32 体系结构中有两种类型的线程:UI 线程和辅助线程。UI 线程绝大多数时间处于空闲状态,等待消息循环中的消息到来。一旦接收到消息,它们就进行处理并等待下一个消息到来。另外,辅助线程用来执行后台处理而且不使用消息循环。Windows 计时器和基于服务器的计时器在运行时都使用 Interval 属性。线程计时器的时间间隔在 Timer 构造函数中设置。计时器的设计目的各不相同,它们的线程处理明确地指出了这一点:
Windows 计时器是为单线程环境设计的,其中,UI 线程用于执行处理。Windows 计时器的精度限定为 55 毫秒。这些传统计时器要求用户代码有一个可用的 UI 消息泵,而且总是在同一个线程中操作,或者将调用封送到另一个线程。对于 COM 组件来说,这样会降低性能。
基于服务器的计时器是为在多线程环境下与辅助线程一起使用而设计的。由于它们使用不同的体系结构,因此基于服务器的计时器可能比 Windows 计时器精确得多。服务器计时器可以在线程之间移动来处理引发的事件。
对消息不在线程上发送的方案中,线程计时器是非常有用的。例如,基于 Windows 的计时器依赖于操作系统计时器的支持,如果不在线程上发送消息,与计时器相关的事件将不会发生。在这种情况下,线程计时器就非常有用。
Windows 计时器位于 System.Windows.Forms 命名空间中,服务器计时器位于 System.Timers 命名空间中,而线程计时器位于 System.Threading 命名空间中。
---------------------------------------------------------------------------------------------------------------- 最近正好做一个web中定期执行的程序,而.net中有3个不同的定时器。所以正好研究研究。这3个定时器分别是://1.实现按用户定义的时间间隔引发事件的计时器。此计时器最宜用于 windows 窗体应用程序中,并且必须在窗口中使用。 system.windows.forms.timer// 2.提供以指定的时间间隔执行方法的机制。无法继承此类。 system.threading.timer//3.在应用程序中生成定期事件。 system.timers.timer这三个定时器位于不同的命名空间内,上面大概介绍了3个定时器的用途,其中第一个是只能在windows窗体中使用的控件。在.net1.1里面,第3个system.timers.timer,也是可以拖拽使用,而.net2.0开始取消了,只能手动编写代码。而后2个没有限制制。下面通过具体的列子来看3个timer的使用和区别,网上谈的很多,但基本都没有代码。一 system.windows.forms.timer#region system.windows.forms.timer public partial class form1 : form { public form1() { initializecomponent(); }int num = 0;private void form_timer_tick(object sender, eventargs e) { label1.text = (++num).tostring(); thread.sleep(3000); }private void button1_click(object sender, eventargs e) { form_timer.start(); }private void button2_click(object sender, eventargs e) { form_timer.stop(); } } #endregion 上面这个是一个很简单的功能,在form窗体上拖了一个system.windows.forms.timer控件名字为form_timer,在属性窗中把enable属性设置为ture,interval是定时器的间隔时间。双击这个控件就可以看到 form_timer_tick方法。在这个方法中,我们让她不停的加一个数字并显示在窗体上,2个按钮提供了对计时器的控制功能。执行的时候你去点击其他窗体在回来,你会发现我们的窗体失去响应了。因为我们这里使用thread.sleep(3000);让当前线程挂起,而ui失去相应,说明了这里执行时候采用的是单线程。也就是执行定时器的线程就是ui线程。timer 用于以用户定义的事件间隔触发事件。windows 计时器是为单线程环境设计的,其中,ui 线程用于执行处理。它要求用户代码有一个可用的 ui 消息泵,而且总是在同一个线程中操作,或者将调用封送到另一个线程。在timer内部定义的了一个tick事件,我们前面双击这个控件时实际是增加了一行代码this.form_timer.tick += new system.eventhandler(this.form_timer_tick); 这个应该明白,不明白的可以看我blog中有关委托和事件的文章。然后windows将这个定时器与调用线程关联(ui线程)。当定时器触发时,windows把一个定时器消息插入到线程消息队列中。调用线程执行一个消息泵提取消息,然后发送到回调方法中(这里的form_timer_tick方法)。而这些都是单线程进行了,所以在执行回调方法时ui会假死。所以使用这个控件不宜执行计算受限或io受限的代码,因为这样容易导致界面假死,而应该使用多线程调用的timer。另外要注意的是这个控件时间精度不高,精度限定为 55 毫秒。我们把interval设置为20ms,然后在start和stop方法中记录当前时,并计算出运行时间:
从上面图可以看到程序执行了7.8s也就是 7800ms,而间隔时间是20ms,也就是最后显示数字应该是390左右,但只有250,显然是不准确的,不过按msdn说的55ms的精度,7800ms应该只执行了140多次或更少。不知道这里是不是理解有问题。二 system.timers.timer接下来就看下另一个timer,我们用他来改写上面的程序#region system.windows.forms.timer public partial class form1 : form { public form1() { initializecomponent(); }int num = 0; datetime time1 = new datetime(); datetime time2 = new datetime(); //定义timer system.timers.timer timers_timer = new system.timers.timer();private void button1_click(object sender, eventargs e) { //手动设置timer,开始执行 timers_timer.interval = 20; timers_timer.enabled = timers_timer.elapsed += new system.timers.elapsedeventhandler(timers_timer_elapsed); time1 = datetime. }void timers_timer_elapsed(object sender, system.timers.elapsedeventargs e) { label1.text = convert.tostring((++num)); //显示到lable thread.sleep(3000); }private void button2_click(object sender, eventargs e) { //停止执行 timers_timer.enabled = time2 = datetime. messagebox.show(convert.tostring(time2-time1)); } } #endregion 我们可以看到这个代码和前面使用form.timer的基本相同,不同的是我们是手动定义的对象,而不是通过拉控件。他也有interval ,enabled 等属性,作用和第一是一样的。不同的是他的事件名为elapsed ,但是和上面的tick一样,绑定一个委托的方法。只是这里我们是手动完成的。另外不同之处是form.timer我们可以用stop和start方法控制,而这里是通过enable属性控制。但实际上也可以用stop和start方法,内部也是通过他自己的enable来控制的。最大的不同就是上面的代码在调试时会报错,提示你&线程间操作无效: 从不是创建控件&label1&的线程访问它。&但如果你不调试直接运行是ok的,而且运行时你去拖动窗体会发现没有出现假死。从这里我们就可以知道这里的timer的创建线程和执行线程不是同一个线程。也就是使用了多线程。timer的创建线程是ui线程,而执行线程是theardpool中的线程,所以不会假死,但调试的时候会报错,因为非控件的创建线程不能操作控件。但你可以直接运行,这里是vs05做了手脚。解决办法很多,用delegate.begininvoke()等等。这里介绍特有的一种方法,设置timer的synchronizingobject属性,timers_timer.synchronizingobject = label1;这样的话,我们的话,调试运行时就不会报错了,但是设置了这个属性timer就编程单线程调用了,就基本和第一个完全一样了。
回答者:葛岚政
Mail: Copyright by ;All rights reserved.SetTimer的时间精度有关问题_VC/MFC大全_优良自学吧 |
当前位置: >
> SetTimer的时间精度有关问题优良自学吧提供SetTimer的时间精度有关问题,SetTimer的时间精度问题今天用SetTimer作为一个计时器,固定时间向另外一个线程发送消息,可是发现Timer的时间精度非常差。测试中我用33ms 来设定SetTimer,得到的时间间隔却是47ms;用50ms得到的时间间隔却是63ms。为什SetTimer的时间精度问题今天用SetTimer作为一个计时器,固定时间向另外一个线程发送消息,可是发现Timer的时间精度非常差。测试中我用33ms 来设定SetTimer,得到的时间间隔却是47ms;用50ms得到的时间间隔却是63ms。为什么会出现这么大的偏差我不知道。不过只是确确实实的情况。请问还有什么其它的方法可以比较准确的进行计时吗?另外固定被通知的线程是继承于CWinThread的,这个线程本身就有消息循环,是否可以在该线程中设定一个计时器呢?------解决方案--------------------SetTimer线程优先级别很低,要等其它的线程执行完后运行它,所以精度度很差,用于要求不高的场合。如果要求高的话可以采用多媒体定时或更高级别的定时方法。
------解决方案--------------------定时器只有30豪秒左右的精度多任务,时间片轮循...精度可能很难保证可以在任何线程中放置定时器有时候,也可以通过为线程的循环配置超时条件(如WaitForSingleObject)来代替定时器,对系统的耗费更低,处理得好,能略为提高响应精度
------解决方案--------------------WM_TIMER消息的优先级比较低,当消息队列里没有其它待处理的高优先级的消息的时候,才会去处理它,如果你的应用程序很繁忙,那么延迟就会很明显。The WM_TIMER message is a low-priority message. The GetMessage and PeekMessage functions post this message only when no other higher-priority messages are in the thread's message queue.
------解决方案--------------------timeBeginPeriod可调节中断频率间隔时间不可能比中断周期还精细,因为计时器最准确也就是每个时钟中断时检查是否到期(本文来自互联网,不代表搜站(/)的观点和立场)本站所有内容来自互联网,若本站收录的信息无意侵犯了贵司版权,请给我们来信(),我们会及时处理和回复,谢谢编辑推荐最近更新

我要回帖

更多关于 如何提高adc精度 的文章

 

随机推荐