1、MFC項目場景如下:
主線程建立了子線程:
CWinThread *m_pThread_SysReset;
m_pThread_SysReset= AfxBeginThread(ThreadSysReset this);
主界面等待子線程退出時,主線程主動調用了函數:
WaitForSingleObject(m_pThread_SysReset->m_hThread, INFINITE);
目的是讓子待線程安全退出,但是子線程此時正在執行SendMesage發消息函數,主線程就會卡死。而如果子線程改為PostMessage發就不會卡死。為什麼呢?
原來在工作線程中使用了SendMesage,它是阻塞方式發消息,這樣的話在主線程中使用了waitforSingleObject,主線程就會被阻塞,要是工作線程也使用了消息循環與主線程相關的操作,那麼因為主線程已經被阻塞了,是以子線程得不到相應,那麼就出現假死了。
實際上,我們可以不使用WaitForSingleObject,因為MFC主線程在不被關閉的話是不會結束的,是以不能使用WaitForSingleObject這樣的函數進行等待。但是很多情況下,我們又需要知道我們建立的工作線程的情況,是以還是需要了解工作線程的傳回值。那麼我們可以使用微軟提供的另一個函數MsgWaitForMultipleObjects。
2、怎麼解決SendMessage當機問題?使用以下源碼即可解決!不再使用WaitForSingleObject,而是使用MsgWaitForMultipleObjects函數。
如此一來,無論子線程怎麼發消息,SendMessage也好,PostMessage也罷,都OK!
m_pThread_SysReset = ThreadFun_StartRun(&m_pThread_SysReset, ThreadSystemReset, this);
void CViewImage::ThreadFun_ExitThread(void)
{
m_bExit = true;
ThreadFun_WaitForObject(&m_pThread_SysReset);//等待線程退出
}
CWinThread *CViewImage::ThreadFun_StartRun(CWinThread **pThread, AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority)
{
if (*pThread != NULL)
{
delete *pThread;
*pThread = NULL;
}
//啟動線程,初始為挂起狀态
*pThread = AfxBeginThread(pfnThreadProc, pParam, nPriority, 0, CREATE_SUSPENDED);
if (*pThread != NULL)
{
//線程結束時不自動撤銷
(*pThread)->m_bAutoDelete = FALSE;
//恢複線程運作
(*pThread)->ResumeThread();
}
return *pThread;
}
void CViewImage::ThreadFun_WaitForObject(CWinThread **pThread)
{
if (*pThread == NULL)
{
return;
}
while (1)
{
DWORD result;
MSG msg;
result = MsgWaitForMultipleObjects(1, &(*pThread)->m_hThread, FALSE, INFINITE, QS_ALLINPUT);
if (result == WAIT_OBJECT_0 + 1)
{
//響應windows消息
PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
//線程運作結束(result==WAIT_OBJECT_0) ||
//傳遞了一個無效的句柄(result==WAIT_FAILED) ||
//線程等待時間已到(result==WAIT_TIMEOUT) ||
//其他情況(...)
break;
}
}
delete *pThread;
*pThread = NULL;
}