如何正確的關閉 MFC 執行緒

發表於2016-11-27

前言:

近日在網上看到很多人問及如何關閉一下執行緒,但是我看網上給出的並不詳細,而且有些方法還是錯誤的。小弟在此拙作一篇,不談別的,只談及如何正確的關閉MFC的執行緒,至於Win32和C RunTime的執行緒暫不涉及。

一.關於MFC的執行緒

1.MFC的執行緒有兩種,一種稱為Work執行緒,一種稱為UI執行緒。一般情況下Work執行緒與UI執行緒的區別主要在於UI執行緒有訊息佇列(並不是有沒有介面,這點要注意,UI執行緒也是可以沒有介面的)。

2.建立這兩種執行緒的區別也不大,可以從建立函式看出。

關於函式的具體使用,請查閱MSDN,這裡不涉及。

二. 結束執行緒前的注意事項

在結束一個執行緒前,只有一點要注意,那就是m_bAutoDelete 的狀態。(什麼?不知道m_bAutoDelete ?!!快去查閱MSDN吧)。

m_bAutoDelete = TRUE; 系統自己清理CWind物件,當然還包括CloseHandle(),ExitInstance()等等一堆函式的呼叫。

m_bAutoDelete = FALSE; 那麼就一定要記得自己在用完後呼叫delete刪除建立執行緒的物件,這一點極為重要,因為不呼叫delete一定會有記憶體洩漏問題。

總之m_bAutoDelete 的值對結束工作是很重要的,這點一定要注意。

三.正確的結束一個Work執行緒

因為Work執行緒是一個全域性函式,或者是一個Static函式,所以它的執行完成也就是它的正常退出了。(什麼?不明白,示例程式碼如下)

1.情況一:

2.情況二:

Work執行緒是個死迴圈或一時半會兒出不來,這時要主執行緒要發個訊息給Work執行緒,讓他退出。

關於主執行緒發一個激發態的訊息給Work執行緒,有多種方法,如在主執行緒裡呼叫SetEvent()等等,你想用什麼都行,但是最好不要在Work執行緒裡用Busy loop的方法。至於為什麼,請參閱《Win32多執行緒程式設計》上面的論述。

四.正確結束一個UI執行緒

因為UI執行緒有訊息佇列,所以結束一個UI執行緒最好的方法是發一個WM_QUIT訊息給訊息佇列,方法很多如:PostQuitMessage(),PostThreadMessage()等等。但是發出訊息後最好等待看UI執行緒是否已經退出(很多人都沒有提及這一點,但是實際工作中發現,加上這一點是多麼的重要)。

五.關於幾個問題的解答

1.問:為什麼我的UI執行緒沒有呼叫ExitInstance()?

答:最大的可能是你的WM_QUIT訊息沒有通知到UI執行緒。為了保險期間最好呼叫PostThreadMessage(),這樣可以指定執行緒的ID。當然如果你對訊息比較熟悉的話,也可以拋一個訊息到最頂層。

2.問:為什麼我的UI執行緒沒有呼叫解構函式?

答:檢檢視你的m_bAutoDelete = FALSE,如果是的話,那麼看你的執行緒物件是否已經delete了。一般情況下呼叫delete會呼叫解構函式。

3.問:在UI執行緒中沒有呼叫WaitForSingleObject(),會怎麼樣?

答:我們知道在PostMessage()之後,函式會馬上返回,如查沒有wait…(),那麼緊接著就呼叫了delete,很有可能物件做的退出操作過程還沒有完成時,又把物件delete掉了,結果還是沒有正常結束。(注:WM_QUIT訊息之後會觸發一堆函式,這個時間是不定的,所以最好Wait…才是正道。)

六.最後不願提的函式

幾乎每本講執行緒的書都會提到下面的函式:

void AfxEndThread(UINT nExitCode);

TerminateThread();

……還有其它的一些極端的函式

我的觀點是:最好不要使用,除非你知道要發生什麼!!

相關文章