1. 程式人生 > >VC++工作者執行緒關閉的問題

VC++工作者執行緒關閉的問題

在使用MFC做一個activex小控制元件時引入了多執行緒,我使用的工作者執行緒,主體功能沒有問題,但是退出IE瀏覽器裡總是發生崩潰的問題,仔細跟了一下,發現是記憶體有洩露,其他的好都好說,new完後,記得delete就可以了,但使用了多執行緒後就比較麻煩,在主執行緒關閉時,可能子執行緒還未來得及關閉,這樣就會導致子執行緒的記憶體洩露,查閱相關文章,大致有如下的解決辦法:

一、為子執行緒增加訊號量,使得在主執行緒有退出操作時,及時通知子執行緒,讓其返回,然後自己釋放掉相關記憶體。下面是引用別人的示例:

 該執行緒的使用模型如下。程式開啟後,使用AfxBeginThread(MYFun, NULL, 0, 0, NULL)建立一個工作者執行緒。其響應函式為
UINT MyFun( LPVOID pParam )
{
     while(1)
     {
            // ......
     }
}
AfxBeginThread返回一個(CWinThread*)型別的指標。
    這個時候,該工程其實有兩個執行緒在執行。一個是主執行緒,另一個就是這個工作者執行緒。問題就是有此帶來的。在主執行緒退出時,工作者執行緒依然在執行。當然,在工程退出時,作業系統自動關閉了這個工作者執行緒。
    解決這個問題的關鍵就是怎麼樣保證工作者執行緒在主執行緒之前退出。
首先,用一個BOOL型別的變數m_bIsValid改造MyFun中的死迴圈。m_bIsValid在建立執行緒之前賦TRUE,MyFun中的死迴圈改為
     while(m_bIsValid)
     {
            // ......
     }
那麼怎麼樣才可以在關閉對話方塊時賦m_bIsValid=FALSE呢?由於基於對話方塊的工程對話方塊dlg類是沒有解構函式的,所以必須手動新增一個dlg類的解構函式。在解構函式中,賦m_bIsValid=FALSE。
    可是,這樣大多數情況下還是有記憶體洩漏的提示存在。這是由於主執行緒太快了!那麼,第二步的關鍵就是怎麼樣讓主執行緒稍微等待工作者執行緒退出了。這個就是小菜一碟了。可以使用訊號量物件。
1 在建立工作者執行緒的之前建立一個訊號量m_hEventExitDlg = CreateEvent(NULL,TRUE,FALSE,NULL),這個訊號量初始是沒有訊號的。
2 在MyFun中的迴圈之後使用SetEvent(m_hEventExitDlg)將這個訊號量置為有訊號。
3 在解構函式中的m_bIsValid=FALSE之後,使用WaitForSingleObject(m_hEventExitDlg, INFINITE)等待這個訊號量。
4 在WaitForSingleObject之後,用CloseHandle(m_hEventExitDlg)關閉這個訊號量。使用這個方法後,也可以將其它需要釋放的資源在此釋放,保證工作者執行緒不會訪問主執行緒已經釋放的資源。
    這樣就確保工作者執行緒在主執行緒之前退出了。
二、在主執行緒退出時,強制終止子執行緒:如下(引用別人示例):
  void   CThreadtestDlg::OnOK()
{
  if(m_pWinThread!=NULL){
		  if(m_pWinThread->m_hThread!=NULL){
						  DWORD   dwExitCode=0;			
						  GetExitCodeThread(m_pWinThread->m_hThread,&dwExitCode);			
										  if(dwExitCode==STILL_ACTIVE){				
										  	TerminateThread(m_pWinThread->m_hThread,0);				
										  }			
						  delete   m_pWinThread;
		  }
 }
  CDialog::OnOK();
}
這兩點經過我測試,第一種最好,第二種雖然也可以使用,比第一種操作簡便。