可等待定时器(获取系统时间)
可等待定时器这种内核对象,它们会在某个指定的时间触发,或每隔一段时间触发一次。它们通常用来在某个时间执行一些操作。
0x01 创建一个可等待定时器 CreateWaitableTimer
(在创建的时候,可等待的计时器对象总是处于未触发状态)
HANDLE WINAPI CreateWaitableTimer(
__in_opt LPSECURITY_ATTRIBUTES lpTimerAttributes, //安全描述符,为NULL时使用默认的
__in BOOL bManualReset, //要创建一个手动重置定时器还是一个自动重置计时器
//当手动重置计时器被触发时,正在等待该计时器的所有线程都会变成可调度状态
//当自动重置计时器被触发时,只有一个正在等待该计时的线程会变成可调度状态
__in_opt LPCTSTR lpTimerName //该可等待计时器的名称
);
0x02 获取一个已经存在的可等待计时器的句柄 OpenWaitableTimer
HANDLE WINAPI OpenWaitableTimer(
__in DWORD dwDesiredAccess, //访问权限
__in BOOL bInheritHandle, //是否允许子进程继承该句柄
__in LPCTSTR lpTimerName //要打开的对象名称
);
0x03 触发计时器 SetWaitableTimer函数
BOOL WINAPI SetWaitableTimer(
__in HANDLE hTimer, //想要触发的计时器
__in const LARGE_INTEGER *pDueTime, //计时器第一次触发的时间
__in LONG lPeriod, //第一次触发后,计时器的触发频度,当给lPeriod参数传0时,我们设置的是一次性定时器,这种定时器只触发一次,之后再不触发。
__in_opt PTIMERAPCROUTINE pfnCompletionRoutine, //异步过程调用APC函数
__in_opt LPVOID lpArgToCompletionRoutine, //APC函数的参数
__in BOOL fResume //是否继续执行,一般传FALSE
);
0x04 将指定的计时器取消 CancelWaitableTimer函数
BOOL WINAPI CancelWaitableTimer(
__in HANDLE hTimer
);
这样计时器就永远不会触发了,除非以后再调用SetWaitableTimer来对它进行重置。如果想要改变触发器的触发时间,不必先调用CancelWaitableTimer,因为每次调用SetWaitableTimer都会在设置新的触发时间之前将原来的触发时间取消掉。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | // 计时器.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <windows.h> #include <iostream> #include <ctime> using namespace std; DWORD WINAPI ThreadProcedure( LPVOID ParameterData); void GetSystemTime(); BOOL __IsLoop = TRUE; int main() { HANDLE ThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProcedure, NULL, 0, NULL); printf ( "Input AnyKey To Exit\r\n" ); getchar (); __IsLoop = FALSE; WaitForSingleObject(ThreadHandle, INFINITE); if (ThreadHandle!=NULL) { CloseHandle(ThreadHandle); ThreadHandle = NULL; } return 0; } DWORD WINAPI ThreadProcedure( LPVOID ParameterData) { //创建一个时钟 HANDLE TimeHandle = NULL; LARGE_INTEGER DueTime; DueTime.QuadPart = -10000000; TimeHandle = CreateWaitableTimer(NULL, FALSE, NULL); //同步事件(SynchronizationEvent) //当事件对象为激发时,如遇到KeWaitForXX等内核函数,事件对象则自动变回未激发态 //通知事件(NotificationEvent) //当事件对象为激发时,如遇到KeWaitForXX等内核函数,事件对象则不会变回未激发态 //If this parameter is TRUE, the timer is a manual-reset notification timer. Otherwise, the timer is a synchronization timer. while (__IsLoop) { if (!SetWaitableTimer(TimeHandle, &DueTime, 0, NULL, NULL, 0)) { printf ( "SetWaitableTimer failed (%d)\n" , GetLastError()); return 0; } BOOL IsOk = WaitForSingleObject(TimeHandle, INFINITE); IsOk -= WAIT_OBJECT_0; if (IsOk==0) { system ( "cls" ); GetSystemTime(); } else { break ; } } CancelWaitableTimer(TimeHandle); CloseHandle(TimeHandle); TimeHandle = NULL; printf ( "ThreadProcedure() Exit\r\n" ); return 0; } void GetSystemTime() { char TimeData[MAX_PATH] = { 0 }; auto TimeObject = time (NULL); tm v1; localtime_s(&v1, &TimeObject); //格式化时间字符串 strftime (TimeData, _countof(TimeData), "%Y-%m-%d %H:%M:%S" , &v1); printf ( "%s\r\n" , TimeData); } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗