1. 程式人生 > >用 QueueUserAPC() 函式來強制執行緒退出等待狀態

用 QueueUserAPC() 函式來強制執行緒退出等待狀態

         當系統建立一個執行緒的時候,會同時建立一個與執行緒相關的佇列。這個佇列被成為非同步過程呼叫(APC)佇列。同時我們也知道,windows提供了6個函式可以等待並將執行緒設定為可提醒狀態--------- 

SleepEx(),

WaitForSingleObjectEx(),

WaitForMultipleObjectsEx(),

SignalObjectAndWait(),

GetQueuedCompletionStatusEx(),

MsgWaitForMultipleObjectsEx()

當我們呼叫這6個函式之一併將執行緒設定為可提醒狀態的時候,系統會首先檢查執行緒的APC佇列。如果佇列中至少有一項,那麼系統不會讓執行緒進入睡眠狀態。

需要牢記:當帶呼叫這些函式的時候,只要執行緒的APC佇列中至少有一項,執行緒就不會進入睡眠狀態。

這個6個函式的返回值也是很重要的:如果是WAIT_IO_COMPLETION,那麼我們就知道執行緒得以執行的原因是執行緒至少處理了APC中的一項。

windows提供了一個函式,允許我們手動的新增一項到指定執行緒的APC佇列中:

DWORD WINAPI QueueUserAPC( 

 __in              PAPCFUNC ,

 __in              HANDLE , 

 __in             ULONG_PTR

)

用這個函式,我們可以強制讓執行緒退出等待狀態,看程式碼:

// QueueUserAPC退出執行緒.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <process.h>
using namespace std;

VOID WINAPI APCFunc(ULONG_PTR dwParam)
{
	//do nothing
	cout<<"APC函式"<<endl;
}

DWORD WINAPI ThreadFun(PVOID pvParam)
{
	HANDLE hEvent  = (HANDLE)pvParam;

	DWORD dw = WaitForSingleObjectEx(hEvent,INFINITE,TRUE);

	if(dw == WAIT_OBJECT_0)
	{
		//如果事件被觸發....
		cout<<"事件觸發"<<endl;
	}

	if(dw == WAIT_IO_COMPLETION)
	{
		//如果執行緒至少處理了APC佇列中的一項
		cout<<"處理了APC 專案"<<endl;
		return 0;
	}

	cout<<"等待成功"<<endl;
	return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
	HANDLE hThread = (HANDLE)_beginthreadex(NULL,0,(unsigned int (__stdcall *)(void *))ThreadFun,(PVOID)hEvent,0,NULL);
	//執行一些其他程式碼

	//此時使用者想要終止子執行緒
	Sleep(1000); //這裡等待一秒很重要,因為最起碼要留出時間先讓子執行緒進入等待(可提醒)狀態哦。
	QueueUserAPC(APCFunc,hThread,NULL);
	WaitForSingleObject(hThread,INFINITE);

	system("pause");
	return 0;
}