有时候会有需要设置某种标志位后,子线程就退出,这也是很常见的话题,通过全局变量可以做到,这篇文章是通过Event对象实现,没有太多需要特别说明的,都是很常见的例子。直接贴上代码来了,函数的名称都很直观。当在键盘上按下CTRL + C时,便会设置线程退出。
/****************************************
*程序名称:EventFunc,采用事件内核对象(Event)控制子线程的退出。
*创建日期:2013年7月18日
****************************************/
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
BOOL InitEventFunc();
BOOL ExitEventFunc();
void ClearEventFunc();
DWORD WINAPI EventFunc(LPVOID pContext);
BOOL WINAPI HandlerRoutine(DWORD dwCtrlType);
typedef struct _THARG{
HANDLE hSignal;
}THAGR;
BOOL ExitFlag = FALSE;
int _tmain(int argc, LPTSTR argv[])
{
SetConsoleCtrlHandler(HandlerRoutine, TRUE);
InitEventFunc();
//wait the thread to set flag TRUE
while (!ExitFlag){
Sleep(5000);
Beep(2000, 300);
}
ClearEventFunc();
_tprintf(_T("main exit!\n"));
return 0;
}
static HANDLE hSignal = NULL, hThread = NULL;
BOOL InitEventFunc()
{
THAGR *pArg = malloc(sizeof(THAGR));
if (!pArg){
_tprintf(_T("malloc failed!\n"));
return FALSE;
}
hSignal = CreateEvent(NULL, FALSE, FALSE, NULL);
if (NULL == hSignal){
_tprintf(_T("CreateEvent failed!\n"));
free(pArg);
return FALSE;
}
pArg->hSignal = hSignal;
hThread = CreateThread(NULL, 0, EventFunc, pArg, 0, NULL);
if (NULL == hThread){
_tprintf(_T("CreateThread failed!\n"));
free(pArg);
CloseHandle(hSignal);
return FALSE;
}
return TRUE;
}
BOOL ExitEventFunc()
{
SetEvent(hSignal);
return TRUE;
}
void ClearEventFunc()
{
//调用SetEvent后直接CloseHandle,会使得hSignal被销毁,子线程上的wait操作会以失败告终。
if (hSignal)
CloseHandle(hSignal);
if (hThread)
CloseHandle(hThread);
}
DWORD WINAPI EventFunc(LPVOID pContext)
{
THAGR *pArg = (THAGR*)pContext;
DWORD dwRet;
while ( (dwRet = WaitForSingleObject(pArg->hSignal, 0)) == WAIT_TIMEOUT ){
_tprintf(_T("In EventFunc, do something!\n"));
Sleep(1000);
}// end while
if (WAIT_OBJECT_0 == dwRet)
_tprintf(_T("EventFunc: event signaled\n"));
else if (WAIT_FAILED == dwRet)
_tprintf(_T("EventFunc: wait event failed, error: %d!\n"), GetLastError());
_tprintf(_T("EventFunc exit!\n"));
//to terminate the main function
ExitFlag = TRUE;
return 0;
}
//处理CTRL+C键盘事件
BOOL WINAPI HandlerRoutine(DWORD dwCtrlType)
{
switch (dwCtrlType)
{
case CTRL_C_EVENT:
ExitEventFunc();
break;
default:
break;
}
return TRUE;
}