1. 程式人生 > >可等待定時器(獲取系統時間)

可等待定時器(獲取系統時間)

led tchar const windows 過程調用 false star napi pri

可等待定時器這種內核對象,它們會在某個指定的時間觸發,或每隔一段時間觸發一次。它們通常用來在某個時間執行一些操作。

  

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);
}

  

可等待定時器(獲取系統時間)