可等待定时器(获取系统时间)

Posted 刘收获

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可等待定时器(获取系统时间)相关的知识,希望对你有一定的参考价值。

可等待定时器这种内核对象,它们会在某个指定的时间触发,或每隔一段时间触发一次。它们通常用来在某个时间执行一些操作。

  

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都会在设置新的触发时间之前将原来的触发时间取消掉。

 

// 计时器.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);
}

  

以上是关于可等待定时器(获取系统时间)的主要内容,如果未能解决你的问题,请参考以下文章

016 可等待计时器对象.6

可等待计时器添加APC测试

如何在切换片段时停止 AsyncTask?

让可等待的计时器添加APC调用

分享几个实用的代码片段(附代码例子)

分享几个实用的代码片段(附代码例子)