博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
精确延时的实现
阅读量:4298 次
发布时间:2019-05-27

本文共 2076 字,大约阅读时间需要 6 分钟。

大家平时写练习程序,包括网站上的范例程序,很多延时都直接用的 Sleep() 实现。这个延时有个缺点,那就是无法统计代码执行的时间。请看下图:

由图可以看到,使用 API 函数 Sleep() 的问题,就是会忽略掉程序的执行时间。很多时候,程序的执行时间是不固定的,所以这就导致使用 Sleep 的延时并不精确,即便 Sleep 使用相同的延时,也可能造成不同电脑上执行速度不同的结果。

图中,理想的延时函数会将程序的执行时间部分考虑进去,这样就可以实现很均匀的延时。下面讨论实现方法。

本次延时要从上次的延时结束开始计算,就必须要记录每次延时执行的具体时刻,而不仅仅是一个时间长度。所以,可以简单的使用 clock() 函数实现,代码如下:

// 精确延时函数(可以精确到 1ms,精度 ±1ms)// by yangw80
, 2011-5-4void HpSleep(int ms){
static clock_t oldclock = clock(); // 静态变量,记录上一次 tick oldclock += ms * CLOCKS_PER_SEC / 1000; // 更新 tick if (clock() > oldclock) // 如果已经超时,无需延时 oldclock = clock(); else while(clock() < oldclock) // 延时 Sleep(1); // 释放 CPU 控制权,降低 CPU 占用率}

直接用函数 HpSleep 替换 Sleep 就可以很直观的看到效果。例如,这个程序,就是用的前述函数实现精确延时。

和 clock() 函数类似的还有 GetTickCount() 函数,clock() 的精度高一些,其精度取决于常量 CLOCKS_PER_SEC,通常在 1ms。根据微软 MSDN 的描述,GetTickCount() 的精度在 10ms~16ms 之间。

以上代码可以实现微秒级的延时。如果需要更高的精确度,可以使用多媒体定时器。做为范例,以下代码实现微秒级的延时,并封装成类:

// 代码名称:精确到微秒的延时类(基于多媒体定时器)// 代码编写:yangw80 
// 最后修改:2011-5-4//      2013-11-2 修改为静态调用//#pragma once#include
class MMTimer{
private: static LARGE_INTEGER m_clk; // 保存时钟信息 static LONGLONG m_oldclk; // 保存开始时钟和结束时钟 static int m_freq; // 时钟频率(时钟时间换算率),时间差public: static void Sleep(int ms);};LARGE_INTEGER MMTimer::m_clk;LONGLONG MMTimer::m_oldclk;int MMTimer::m_freq = 0;// 延时void MMTimer::Sleep(int ms){
if (m_oldclk == 0) {
QueryPerformanceFrequency(&m_clk); m_freq = (int)m_clk.QuadPart / 1000; // 获得计数器的时钟频率 // 开始计时 QueryPerformanceCounter(&m_clk); m_oldclk = m_clk.QuadPart; // 获得开始时钟 } unsigned int c = ms * m_freq; m_oldclk += c; QueryPerformanceCounter(&m_clk); if (m_clk.QuadPart > m_oldclk) m_oldclk = m_clk.QuadPart; else do {
::Sleep(1); QueryPerformanceCounter(&m_clk); // 获得终止时钟 } while(m_clk.QuadPart < m_oldclk);}

看明白了前面的叙述,这个代码应该很容易就能看懂。

使用方法:将以上代码拷贝到新建的 MMTimer.h 中,然后在主程序中加上 #include "MMTimer.h",在需要 Sleep 的地方执行 MMTimer::Sleep 方法。

为了简单起见,只写了一个 .h 文件。更标准一些的做法,是将前述代码再分离出一个 MMTimer.cpp 文件,甚至改掉 MMTimer 这个名字,或者封装成库等等,这些就不再多说了,本文只想阐述一个方法。

来源:http://www.easyx.cn/skills/View.aspx?id=73

转载地址:http://vqnws.baihongyu.com/

你可能感兴趣的文章
经典SQL语句大全
查看>>
Eclipse快捷键 10个最有用的快捷键
查看>>
log日志记录是什么
查看>>
<rich:modelPanel>标签的使用
查看>>
<h:commandLink>和<h:inputLink>的区别
查看>>
<a4j:keeyAlive>的英文介绍
查看>>
关于list对象的转化问题
查看>>
VOPO对象介绍
查看>>
suse创建的虚拟机,修改ip地址
查看>>
linux的挂载的问题,重启后就挂载就没有了
查看>>
docker原始镜像启动容器并创建Apache服务器实现反向代理
查看>>
docker容器秒死的解决办法
查看>>
管理网&业务网的一些笔记
查看>>
openstack报错解决一
查看>>
openstack报错解决二
查看>>
linux source命令
查看>>
openstack报错解决三
查看>>
乙未年年终总结
查看>>
子网掩码
查看>>
第一天上班没精神
查看>>