time(), clock(), gettimeofday()等库函数需要2次查询当前时间点,比较差值,才能判断经过多少时间。也就是说如果需要在1S后触发一个动作,就需要延时等待,而且要一直保持查询,这样就属于阻塞方式了,会浪费大量CPU时间。
对于非阻塞方式,Linux下有alarm和setitime定时调用任务处理函数,可是Windows下要如何用非阻塞方式定时回调任务处理函数呢?
可以使用Windows API timeSetEvent(). 本文介绍如何在Win10x64专业版 + eclipse photon + CDT + MinGW环境下, 设置非阻塞方式的定时调用自定义任务处理函数,以达到周期性调用目的。
使用timeSetEvent 需要引入"WinMM.Lib"。
eclipse + CDT + MinGW C Linker引入方法: 1)检查库文件WinMM.Lib及路径 检查路径下是否包含该lib文件,如果不包含需要重新下载,并放入推荐的默认路径(路径非必须按默认设置)。 文件默认路径是 C:\Program Files (x86)\Microsoft SDKs\Windows\v6.0A\bin\WinMM.Lib 推荐一个下载链接: http://www.opdown.com/soft/125224.html 2)eclipse链接WiMM.lib库 右键eclipse工程 属性->C/C++ Build -> Settings -> MinGW C Linker -> Libraries,Library search path (-L)添加路径,Libraries (-I) 添加文件(注意不要带后缀名.lib,不然会报错"ld.exe: cannot find -lWinMM.lib 3)工程代码配置 工程中无需使用预编译指令 #pragma comment (lib,"WinMM.Lib")。这点与VS平台不一样。 4)代码编写
#include <windows.h> static int cnt = 0; void CALLBACK onTimeFunc(UINT wTimerID,UINT msg, DWORD dwUser,DWORD dw1,DWORD dw2) { cnt ++; time_t nowtime; time(&nowtime); char *p = ctime(&nowtime); printf("%s", p); fflush(stdout); // 强制刷新流 stream 的输出缓冲区 } int main() { MMRESULT timer_id = timeSetEvent( 1000, // 以毫秒指定事件的周期 1, // 精度, 默认1ms &onTimeFunc, // 回调函数地址 (DWORD)1, // 存放用户提供的回调数据 TIME_PERIODIC); // TIME_ONESHOT -- 执行一次; TIME_PERIODIC -- 周期性执行; if(!timer_id) { printf("timeSetEvent() failed with error %ld \n ", GetLastError()); return -1; } while(cnt < 10) { Sleep(100); // 睡眠, 精度1ms } timeKillEvent(timer_id); // 释放定时器 return EXIT_SUCCESS; }
输出
Sun Apr 26 16:24:54 2020 Sun Apr 26 16:24:55 2020 Sun Apr 26 16:24:56 2020 Sun Apr 26 16:24:57 2020 Sun Apr 26 16:24:58 2020 Sun Apr 26 16:24:59 2020 Sun Apr 26 16:25:00 2020 Sun Apr 26 16:25:01 2020 Sun Apr 26 16:25:02 2020 Sun Apr 26 16:25:03 2020
REF: https://www.cnblogs.com/lancidie/archive/2011/04/06/2006729.html https://blog.csdn.net/bluebulesky/article/details/5222059