使用?c++?在?windows?上定時(shí)執(zhí)行一個(gè)函數(shù)的示例代碼
#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; } }
這里主要用到的幾個(gè) win32api 為
MMRESULT timeBeginPeriod使用該 api 需要鏈接
Winmm
, 所以我們?cè)谖募敳考尤?code>#pragma comment( lib, "Winmm" ).
它的作用是請(qǐng)求提高一些計(jì)時(shí)器的精度比如這里的Sleep
, 默認(rèn) windows 似乎只會(huì)給我們提供 10ms 左右很粗糙的精度, 所以這里我們直接請(qǐng)求盡可能的高的精度, 即1ms
.QueryPerformanceFrequency該 api 用于獲取"性能計(jì)時(shí)器"的精度, 單位是 ticks每秒. 在我的機(jī)子上它的值是
10000000
, 可以看到精度還是很令人滿(mǎn)意的. 在這里我們將其與expected
(也就是期望每次調(diào)用的間隔,單位s)進(jìn)行相乘, 得到一個(gè)以ticks為單位的間隔.QueryPerformanceCounter該 api 會(huì)檢測(cè)"性能計(jì)時(shí)器"的值, 單位為 ticks, 在 msdn 中其精度的描述為 <1us.
那么結(jié)合上述幾個(gè) api 以及幾個(gè)簡(jiǎn)單的數(shù)學(xué)運(yùn)算, 這樣就可以相對(duì)穩(wěn)定的定時(shí)調(diào)用函數(shù)了(在這里是 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
當(dāng)你注釋掉timeBeginPeriod
的調(diào)用后你會(huì)發(fā)現(xiàn)結(jié)果不是很樂(lè)觀(即使我們期望 1s 調(diào)用 60 次):
time out, counter=33 time out, counter=31 time out, counter=32 time out, counter=31
最后, 這個(gè)可能常見(jiàn)于游戲的幀率控制, 實(shí)際上我就是從這里知道的這些東西(x
到此這篇關(guān)于使用 c++ 在 windows 上穩(wěn)定定時(shí)執(zhí)行一個(gè)函數(shù)的文章就介紹到這了,更多相關(guān)c++定時(shí)執(zhí)行函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
opencv3/C++關(guān)于移動(dòng)對(duì)象的輪廓的跟蹤詳解
今天小編就為大家分享一篇opencv3/C++關(guān)于移動(dòng)對(duì)象的輪廓的跟蹤詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12C++日期類(lèi)的實(shí)現(xiàn)日期計(jì)算器舉例詳解
這篇文章主要給大家介紹了關(guān)于C++日期類(lèi)實(shí)現(xiàn)日期計(jì)算器的相關(guān)資料,我們要考慮日期的增加和減少,自增和自減,以及兩個(gè)日期類(lèi)的比較,以及當(dāng)前日期類(lèi)的日期顯示和用戶(hù)的輸入輸出,需要的朋友可以參考下2024-05-05C++異常處理方式實(shí)例詳解(超級(jí)詳細(xì)!)
程序有時(shí)會(huì)遇到運(yùn)行階段錯(cuò)誤,導(dǎo)致程序無(wú)法正常執(zhí)行下去,c++異常為處理這種情況提供了一種功能強(qiáng)大的而靈活的工具,下面這篇文章主要給大家介紹了關(guān)于C++異常處理方式的相關(guān)資料,需要的朋友可以參考下2023-04-04C++實(shí)現(xiàn)日期類(lèi)(Date類(lèi))的方法
下面小編就為大家?guī)?lái)一篇C++實(shí)現(xiàn)日期類(lèi)(Date類(lèi))的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-01-01