APC 简介

 

默认情况下,创建线程时不会创建这个APC队列

调用了QueueUserAPC函数或其他可向APC队列添加函数之后,才会创建APC这个队列;

每个线程都有自己的APC队列 , 当线程处在alertable状态时才去执行这些APC函数.

alertable :  当线程调用例如: WaitForSingleObjectEx , SleepEx 等带ex 的函数, 并把bAlterable参数设置TRUE;

只有当APC队列中的所有函数都被执行完毕后线程函数才会被唤醒来继续执行, 按fifo调用顺序;

 

第一个例子:

void __stdcall apc_func(
	ULONG_PTR dwParam
	)
{
	printf("%d is running\n", dwParam);
	Sleep(500);
}


// QueueUserAPC把一个apc函数添加到指定线程的apc队列
void test_apc(){
	for (int i = 0; i < 10; ++i)
		QueueUserAPC(apc_func, GetCurrentThread(), i);
	SleepEx(-1, TRUE); // Alterable , 如果FALSE则不执行
	printf("end\n");
}

int _tmain(int argc, _TCHAR* argv[])
{
	_tsetlocale(LC_CTYPE, TEXT(""));
    test_apc();
	return 0;
}

 

 

第2个例子: 注意 Wait....ex 这类函数的返回值;

void __stdcall apc_func2(
	ULONG_PTR dwParam
	)
{
	_tprintf(TEXT("apc_func tid:%d\n"), GetCurrentThreadId());
	Sleep(500);
}



unsigned int __stdcall tproc(void *param)
{
    //添加 apc 函数, 
	for (int i = 0; i < 5; ++i)
		QueueUserAPC(apc_func2, GetCurrentThread(), i);

	_tprintf(TEXT("线程开始 tid:%d\n"),GetCurrentThreadId());

	HANDLE e = (HANDLE)param;

    //注意参数, 只有当所有apc执行完后才返回,返回值与SetEvent 不一样
	DWORD  ret = WaitForSingleObjectEx(e, -1, TRUE);
	switch (ret)
	{
	case WAIT_OBJECT_0: _tprintf(TEXT("事件触发!\n")); break;
	case WAIT_IO_COMPLETION:_tprintf(TEXT("APC队列执行完了!\n")); break;
	case WAIT_FAILED:_tprintf(TEXT("WaitForSingleObjectEx 失败\n")); break;
	}
	_tprintf(TEXT("end\n"));
	return 0;
}
void test_apc2()
{
    //一个事件 
	HANDLE e = CreateEvent(NULL, TRUE,FALSE,NULL);
    
	HANDLE t = (HANDLE)_beginthreadex(0, 0, tproc, (void*)e, 0,NULL);

	WaitForSingleObject(t, -1);
}
int _tmain(int argc, _TCHAR* argv[])
{
	_tsetlocale(LC_CTYPE, TEXT(""));
	
	test_apc2();
	


	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值