很多地方要用到高精度定时器,比如实时通信、多媒体处理、游戏开发等。
我开发的软交换系统中,多媒体处理要用到高精度的定时器,在windows下常见的做法是:
先设置定时器精度为1毫秒:
timeBeginPeriod(1);
这步很关键,否则定时器的精度很低,大概只有15.6毫秒,基本不能用。
然后使用这样一组函数:
CreateTimerQueue();
CreateTimerQueueTimer(&t, timer, (WAITORTIMERCALLBACK)OneMilliSecondProc, this, 0, 10, 0); // 每10毫秒调用一次回调函数
但最近发现在最新版的windows10下出问题了,设置精度为1毫秒,程序也没有出错,但实际的精度降低到15.6毫秒,实际上精度设置完全不起作用了。
苦思良久不得其解,后来搜到一篇老外写的文章:
Windows Timer Resolution: The Great Rule Change(Windows计时器分辨率:极大的规则更改)
原来是微软故意这么干的,他觉得设置精度到毫秒级别,太耗费资源了,如果是移动设备,频繁唤醒切换线程,电池消耗得很快。于是微软宁肯抛弃强兼容性传统,也坚决让这函数失效。
怎么办?
解决方法是使用C++1x的时间函数,自己封装一个定时器,下面为示例代码:
// 定时器函数
int Timer11()
{
chrono::steady_clock::time_point tp = std::chrono::steady_clock::now();
auto dt_micri = std::chrono::microseconds(10000); // 10ms
while (true) {
tp += dt_micri;
this_thread::sleep_until(tp);
// 回调函数,应用写在这函数里
OneMilliSecondProc();
}
return(0);
}
// 调用的例子
thread thd(Timer11); // 创建线程
thd.detach();
我的编译器是Microsoft Visual C++ 2017。经过测试,发现这个方法制作的定时器精度相当高,而且代码简单,通用,在最新版本的windows10下工作正常,运行良好。