可等待的计时器与APC调用

以前第一次看到APC,也就是异步过程调用的时候,没有搞明白这是一个什么样的机制。
今天再看一次,然后结合一些简单的测试代码和搜索来的资料,大概明白了是怎么回事。

 

先来非常简单地描述一下这一个“可等待的计时内核对象”。

大概定义如下:

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

 

相关的API(具体参数请参阅MSDN):

 

创建一个可等待的计时器:CreateWaitableTimer

得到一个已经存在的可等待的计时器的句柄:OpenWaitableTimer

设置可等待的计时器:SetWaitableTimer

 

 

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

Miscrosoft允许计时器把一个异步过程调用(Asynchronnous procedure call,APC)放到调用线程的队列中。将这一个异步过程调用放到调用线程的队列中,是通过调用SetWaitableTimer并利用类型为PTIMERAPCROUTINE的一个参数,这个参数其实是一个函数指针类型,所以异步过程的地址就是传到这里。想要线程调用这些异步过程,线程还必须处于可提醒状态,也就是通过调用SleepEx,WaitForSingleObjectEx,WaitForMultipleObjectEx,MsgWaitForMultipleObjectEx而进入的等待状态。这些函数都有一个参数,指是线程是否进入可提醒状态。

 

示例代码:

 

#define _WIN32_WINNT 0x0400   


#include<windows.h>
#include<windowsx.h>   //这里面只包含一些宏,不包括一些类型定义
#include<tchar.h>
#include<stdio.h>


VOID APIENTRY TimerAPCRoutine(PVOID pvArgToCompletionRoutine,
							  DWORD dwTimerLowValue,DWORD dwTimerHighValue) ;


int main(void)
{
	HANDLE hTimer ;
	LARGE_INTEGER li ;
  
	hTimer = CreateWaitableTimer(NULL,FALSE,NULL) ;

	const int nTimerUnitsPerSecond = 10000000 ;

	li.QuadPart = -(5 * nTimerUnitsPerSecond) ; //负值代表相对时间

	SetWaitableTimer(hTimer,&li,6*60*60*1000,TimerAPCRoutine,NULL,FALSE) ;

	printf("Main Thread Sleep for INFINE\n") ;

	SleepEx(INFINITE,TRUE) ;

	printf("Main Thread Wake Up\n") ;

	CloseHandle(hTimer) ;

	return 0 ;
}


VOID APIENTRY TimerAPCRoutine(PVOID pvArgToCompletionRoutine,
								DWORD dwTimerLowValue,DWORD dwTimerHighValue) 
{
	printf("APC Fuction\n") ;

	return ;
}



程序大概的执行流程就是:创建一个可等待的计时器并添加一个异步过程调用,随之调用SleepEx进入可提醒状态。当计时器触发时,调用SetWaitableTimer的线程就会调用APC队列中的一项,也就是我们刚才传入的函数地址。执行完毕后,线程随即从SleepEx调用中返回。大概流程就是这样。

PS:如果调用SleepEx时,APC队列不为空,则线程不会睡眠,而是调用APC队列中的一项,直到APC队列为空。当调用那些让线程睡眠的函数时,当且仅当线程的APC队列中一项都没有的时候,这些函数才会将线程挂起。

还值得一提的是,这一个让可等待的计时器添加APC调用的机制,有点类似Linux下的处理alarm信号的信号处理函数。

 

 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值