VC中基于 Windows 的精确定时 示例工程下载 COleDateTime start_time = COleDateTime::GetCurrentTime(); COleDateTimeSpan end_time= COleDateTime::GetCurrentTime()-start_time; while(end_time.GetTotalSeconds()< 2) //实现延时2秒 { MSG msg; GetMessage(&msg,NULL,0,0); TranslateMessage(&msg); DispatchMessage(&msg); //以上四行是实现在延时或定时期间能处理其他的消息, //虽然这样可以降低CPU的占有率, //但降低了延时或定时精度,实际应用中可以去掉。 end_time = COleDateTime::GetCurrentTime()-start_time; }//这样在延时的时候我们也能够处理其他的消息。方式四:在精度要求较高的情况下,VC中可以利用GetTickCount()函数,该函数的返回值是 DWORD dwStart = GetTickCount(); DWORD dwEnd = dwStart; do { dwEnd = GetTickCount()-dwStart; }while(dwEnd <50);为使GetTickCount()函数在延时或定时期间能处理其他的消息,可以把代码改为: DWORD dwStart = GetTickCount(); DWORD dwEnd = dwStart; do { MSG msg; GetMessage(&msg,NULL,0,0); TranslateMessage(&msg); DispatchMessage(&msg); dwEnd = GetTickCount()-dwStart; }while(dwEnd <50);虽然这样可以降低CPU的占有率,并在延时或定时期间也能处理其他的消息,但降低了延时或定时精度。 方式五:与GetTickCount()函数类似的多媒体定时器函数DWORD timeGetTime(void),该函数定时精 方式六:使用多媒体定时器timeSetEvent()函数,该函数定时精度为ms级。利用该函数可以实现周期性的函数调用。如示例工程中的Timer6和Timer6_1。函数的原型如下: MMRESULT timeSetEvent( UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, WORD dwUser, UINT fuEvent )该函数设置一个定时回调事件,此事件可以是一个一次性事件或周期性事件。事件一旦被激活,便调用指定的回调函数, uDelay:以毫秒指定事件的周期。 Uresolution:以毫秒指定延时的精度,数值越小定时器事件分辨率越高。缺省值为1ms。 LpTimeProc:指向一个回调函数。 DwUser:存放用户提供的回调数据。 FuEvent:指定定时器事件类型: TIME_ONESHOT:uDelay毫秒后只产生一次事件 TIME_PERIODIC :每隔uDelay毫秒周期性地产生事件。具体应用时,可以通过调用timeSetEvent()函数,将需要周期性执行的任务定义在LpTimeProc回调函数 方式七:对于精确度要求更高的定时操作,则应该使用QueryPerformanceFrequency()和 QueryPerformanceFrequency()函数和QueryPerformanceCounter()函数的原型如下: BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency); BOOL QueryPerformanceCounter(LARGE_INTEGER *lpCount);数据类型ARGE_INTEGER既可以是一个8字节长的整型数,也可以是两个4字节长的整型数的联合结构, typedef union _LARGE_INTEGER { struct { DWORD LowPart ;// 4字节整型数 LONG HighPart;// 4字节整型数 }; LONGLONG QuadPart ;// 8字节整型数 }LARGE_INTEGER ;在进行定时之前,先调用QueryPerformanceFrequency()函数获得机器内部定时器的时钟频率, LARGE_INTEGER litmp; LONGLONG QPart1,QPart2; double dfMinus, dfFreq, dfTim; QueryPerformanceFrequency(&litmp); dfFreq = (double)litmp.QuadPart;// 获得计数器的时钟频率 QueryPerformanceCounter(&litmp); QPart1 = litmp.QuadPart;// 获得初始值 do { QueryPerformanceCounter(&litmp); QPart2 = litmp.QuadPart;//获得中止值 dfMinus = (double)(QPart2-QPart1); dfTim = dfMinus / dfFreq;// 获得对应的时间值,单位为秒 }while(dfTim<0.001);其定时误差不超过1微秒,精度与CPU等机器配置有关。 下面的程序用来测试函数Sleep(100)的精确持续时间: LARGE_INTEGER litmp; LONGLONG QPart1,QPart2; double dfMinus, dfFreq, dfTim; QueryPerformanceFrequency(&litmp); dfFreq = (double)litmp.QuadPart;// 获得计数器的时钟频率 QueryPerformanceCounter(&litmp); QPart1 = litmp.QuadPart;// 获得初始值 Sleep(100); QueryPerformanceCounter(&litmp); QPart2 = litmp.QuadPart;//获得中止值 dfMinus = (double)(QPart2-QPart1); dfTim = dfMinus / dfFreq;// 获得对应的时间值,单位为秒由于Sleep()函数自身的误差,上述程序每次执行的结果都会有微小误差。下列代码实现1微秒的精确定时: LARGE_INTEGER litmp; LONGLONG QPart1,QPart2; double dfMinus, dfFreq, dfTim; QueryPerformanceFrequency(&litmp); dfFreq = (double)litmp.QuadPart;// 获得计数器的时钟频率 QueryPerformanceCounter(&litmp); QPart1 = litmp.QuadPart;// 获得初始值 do { QueryPerformanceCounter(&litmp); QPart2 = litmp.QuadPart;//获得中止值 dfMinus = (double)(QPart2-QPart1); dfTim = dfMinus / dfFreq;// 获得对应的时间值,单位为秒 }while(dfTim<0.000001);其定时误差一般不超过0.5微秒,精度与CPU等机器配置有关。(完) |
最新评论 [发表评论] [文章投稿] | 查看所有评论 推荐给好友 打印 |
记得没错的话这篇文章应该是大连理工大学一位博士的原创。 ( four 发表于 2007-3-30 20:39:00) 找到我问题的原因了,我时间处理时间要大于周期1ms 。好东西,太精确了。 ( lzl1010 发表于 2006-3-17 16:26:00) 我用的是第7种定时器。 ( lzl1010 发表于 2006-3-17 16:21:00) 好。我有一个程序,每1ms读一次usb设备,按开始按钮时开始读,按停止按钮停止读。按停止按钮停不下来,之后程序就没有回应了,查看cpu 使用率为100%,太占系统资源了。 ( lzl1010 发表于 2006-3-17 16:18:00) 你好,我是数据库编程的初学者,请问当点击一个按钮进入下一页面的时候有时总是会出现一个错误:提示指针错误或者检查记录出错,但还是能进入下一页面,请问是为什么? 还有就是无效的游标状态又是怎么回事?? ( 153375424 发表于 2005-11-28 0:18:00) 你好,我是数据库编程的初学者,请问当点击一个按钮进入下一页面的时候有时总是会出现一个错误:提示指针错误或者检查记录出错,但还是能进入下一页面,请问是为什么? 还有就是无效的游标状态又是怎么回事?? ( 153375424 发表于 2005-11-28 0:18:00) 不错,很全面 ( hkbs_1121 发表于 2005-3-31 13:44:00) 写得很好....谢谢.. ( ot512 发表于 2004-12-6 12:12:00) 以下是个人想法: 首先,在应用程序级做精确定时是相当艰难的。 这里面很多因素要考虑:比如多任务操作系统固有的任务切换;其他驱动程序的CPU时间的抢占;高优先级应用程序的执行;不确定的操作系统的作业任务分配规则(其实低优先级的线程也可以获得运行)等等许多问题,都可以导致定时的不精确。 其实,即使在驱动程序级别要想做到精确定时也非易事,这里面还有定时间隔的准确度和精度问题。直接采用计算机的原有硬件,由于计算机的个体差异,会导致定时精度在总体上难以保障。所以,要提高精度,许多人还是采用了专用外围定时集成电路的方法。通过驱动程序和硬件相结合,以达到高精度的定时。 ( guojian 发表于 2004-12-2 11:37:00) 好文章,windwos下的定时其本都全了 TO:tyj_yy:"精确"计时是不可能的,精确是相对,你相精确到多少?你能做出更好的吗?多任务就不行了吗?你把优先级调高了,还是很精确的,我用过timeGetTime,其本可以定们到1ms TO:guojian "window多任务,在这里发生了任务切换,执行时间2ms" 定时应该没错,因为CPU不会连续让他运行2ms,CPU的时间片很小,只要定时的间隔大于计数器的时钟频率和CPU的时间片,应该是可以的.计数器的时钟频率和CPU的时间片好像是相关的(个人认为) |