毫秒级计时器

今天继续编写,基于框架的效果编辑器,修正了部分BUG后。。就想把。渲染窗口挂到MFC的窗口上。。。做为整个编辑器的一个子窗口打开。。这次。。。也比较方便。。也便于以后修改。以前挂接渲染窗口时。是使用settime来进行定时刷新渲染窗口,原来就感觉到刷新比较慢。但是因为查看MSDN。。。上讲。。SetTime是毫秒级。。。最低精确到1毫秒。。。1秒=1000毫秒。我为了保证窗口UI的正常使用。一般设置为20毫秒。。为什么不用线程咧。因为渲染窗口一般会与其它信息存在交互。。单纯渲染线程。。在处理互斥时。。。效率会慢到无法用言语来表达。。。1000/20=50。。每秒50的fps。。足可以应付简单的渲染需求了。但是在今天的测试中。。动态调整动画的FPS时。。。确发现。当FPS超过每秒20的范围后。。动画就不再有任何变化了,郁闷。。。然后。。就轻易的推翻了自己写的一切。。。使用线程。。渲染。。。。因为渲染纹理是从一个模板LIST中。。。获得。。。立刻就开始徘徊在。。加锁。。。。。巨慢。。。不加锁。。。异常的围城中。。。。在多方思索无果后。。。。忽然觉得SetTime不应该会如此慢的。。。。然后。。。放弃线程。。。去实际测试了一下。。。发现了问题:

SetTime虽然MSDN上说可以最低设置到一毫秒,但实际上测试只能精确到53毫秒左右,然后google上查询。。。有了答案。windows 以经限定了Settimer()的精度是55ms。。。就是所谓的1000/55==18.2 ..因为98系统是根据时间中断反馈,而时间中段每秒最多18.2次,虽然2000的系统据说没有此限制。。但在我XP的系统下测试。。。精度依旧。应该是为了保证系统兼容。。所以将SetTime精度设定在最高的范围。。如果这样换算。。。也就和我的问题基本吻合。。。。SetTime(1)的情况下。。实现是55毫秒触发一次,也就是每秒18.2帧。。。。18的FPS。。。啥都玩不转了。而且WM-TIME消息 在系统的优先级为极低。很容易被抛弃。。渲染窗口最少要保证在20毫秒触发一次。。也就是FPS50的情况下。。才可以保证动画等效果的连续性。。怎么办。。。怎么办。。。。继续google。。。毫秒级记时器。。。。。终于被我找到了。。。。。好几种解决的方法,对了。。。sleep的精度是30MS。。。以后要注意。。一下:

一.GetTickCount()函数,该函数的返回值是  DWORD型,表示以ms为单位的计算机启动后经历的时间间隔。精度比WM_TIMER消息映射高,在较 短的定时中其计时误差为15ms,在较长的定时中其计时误差较低,如果定时时间太长,就好象死机一样,CPU占用率非常高,只能用于要求不高的延时程序中.
下列代码可以实现50ms的精确定时:
       DWORD dwStart = GetTickCount();
DWORD dwEnd   = dwStart;
do
{
              //为了在延迟时间不阻塞。可在此将消息传出,但是会降低精度
MSG   msg;
GetMessage(&msg,NULL,0,0);
TranslateMessage(&msg);
DispatchMessage(&msg);
              dwEnd = GetTickCount()-dwStart;
}while(dwEnd <50);
二,这就是我现在使用的方法,也决定以后都使用。。哈哈
 使用多媒体定时器timeSetEvent()函数,该函数定时精度为ms级(精度基本准确,由于挂接窗口一般是在工具中实现,内部人员使用,所以不需要控制机器配置)。
MMRESULT timeSetEvent( UINT uDelay,
UINT uResolution,
LPTIMECALLBACK lpTimeProc,
WORD dwUser,
UINT fuEvent )
该函数设置一个定时回调事件,此事件可以是一个一次性事件或周期性事件。事件一旦被激活,便调用指定的回调函数, 成功后返回事件的标识符代码,否则返回NULL
参数说明:
uDelay:以毫秒指定事件的周期。
Uresolution:以毫秒指定延时的精度,数值越小定时器事件分辨率越高。缺省值为1ms。
LpTimeProc:指向一个回调函数。
DwUser:存放用户提供的回调数据。
FuEvent:指定定时器事件类型:
TIME_ONESHOT:uDelay毫秒后只产生一次事件
TIME_PERIODIC :每隔uDelay毫秒周期性地产生事件。  
需要注意的是,任务处理的时间不能大于周期间隔时间。另外,在定时器使用完毕后, 应及时调用timeKillEvent()将之释放。 
虽然还有更加精确的计时方法,不过对于我的需求这个以经够用了
我的实现代码
UINT   uTimerID;         //定义定时器句柄   
void   CALLBACK   TimerCallProc(UINT   TimerID,   UINT   msg,DWORD   dwUser,   DWORD   dwa,DWORD   dwb)   
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值

 Sleep(1);
}
//当前设置为1ms...
uTimerID=timeSetEvent(1,1,&TimerCallProc,0,TIME_PERIODIC);
//退出时
 timeKillEvent(uTimerID);                   //删除定时器事件   
 timeEndPeriod(1);                          //清除定时器分辨率  



 

posted on 2007-10-17 17:38 Randy 阅读(5466) 评论(1)  编辑 收藏 引用

评论

# re: 毫秒级计时器 2012-12-03 11:53 外贸领航

国外新闻http://www.ciqol.net/seenews  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2007年10月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

导航

统计

常用链接

留言簿(3)

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜