#include <iostream>
#include <Windows.h>
#include <thread>
#pragma comment( lib, "Winmm" )
static int counter = 0;
static int64_t ticks_per_second;
void __stdcall on_timer(HWND h, UINT ui, UINT_PTR up, DWORD dw)
{
std::cout << "time out, counter=" << counter << std::endl;
counter = 0;
}
void get_message_trd_func()
{
SetTimer(NULL, 0, 1000, on_timer);
MSG msg;
while (GetMessageA(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
}
int main()
{
std::cout << "go!" << std::endl;
timeBeginPeriod(1);
QueryPerformanceFrequency((LARGE_INTEGER*)&ticks_per_second);
const double expected = 1.0 / 60.0;
const int64_t expected_ticks = (int64_t)(expected * ticks_per_second);
std::thread thr(get_message_trd_func);
for (;;)
{
int64_t before_ticks = 0;
QueryPerformanceCounter((LARGE_INTEGER*)&before_ticks);
// do something...
for (int i = 0; i < 10000; i++)
{
float a = i * i + i + sin(i) + sqrt(i);
}
int64_t after_ticks = 0;
QueryPerformanceCounter((LARGE_INTEGER*)&after_ticks);
counter++;
int64_t ticks_need_sleep = expected_ticks - (after_ticks - before_ticks);
double ms_need_sleep = (double)ticks_need_sleep / ticks_per_second * 1000.0;
if (ms_need_sleep >= 1.0)
Sleep((DWORD)ms_need_sleep);
else
continue;
}
}
这里主要用到的几个 win32api 为
-
MMRESULT timeBeginPeriod
使用该 api 需要链接Winmm
, 所以我们在文件顶部加入#pragma comment( lib, "Winmm" )
.
它的作用是请求提高一些计时器的精度比如这里的Sleep
, 默认 windows 似乎只会给我们提供 10ms 左右很粗糙的精度, 所以这里我们直接请求尽可能的高的精度, 即1ms
. -
QueryPerformanceFrequency
该 api 用于获取"性能计时器"的精度, 单位是 ticks每秒. 在我的机子上它的值是10000000
, 可以看到精度还是很令人满意的. 在这里我们将其与expected
(也就是期望每次调用的间隔,单位s)进行相乘, 得到一个以ticks为单位的间隔. -
QueryPerformanceCounter
该 api 会检测"性能计时器"的值, 单位为 ticks, 在 msdn 中其精度的描述为 <1us.
那么结合上述几个 api 以及几个简单的数学运算, 这样就可以相对稳定的定时调用函数了(在这里是 1s 60 次):
time out, counter=59
time out, counter=59
time out, counter=60
time out, counter=59
time out, counter=58
time out, counter=60
当你注释掉timeBeginPeriod
的调用后你会发现结果不是很乐观(即使我们期望 1s 调用 60 次):文章来源:https://www.toymoban.com/news/detail-588321.html
time out, counter=33
time out, counter=31
time out, counter=32
time out, counter=31
最后, 这个可能常见于游戏的帧率控制, 实际上我就是从这里知道的这些东西(x文章来源地址https://www.toymoban.com/news/detail-588321.html
到了这里,关于使用 c++ 在 windows 上稳定定时执行一个函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!