2014-01-20 166 views
2

我正在開發MFC應用程序。 UI線程啓動工作線程並在應用程序關閉時停止它。問題是每次嘗試刪除線程時,應用程序都會崩潰。刪除線程時發生崩潰

這裏是代碼:

首先Thread類和它的實現:

class FileThread : public CWinThread 
{ 
public: 
    static FileThread* CreateWorkerThread(LPVOID params, UINT priority, UINT flags); 

    void InitThread(); 
    void StopThread(); 
    inline HANDLE GetStopHandle() const { return m_stopThread; } 
    inline HANDLE GetWaitHandle() const { return m_waitThread; } 

private: 
    HANDLE m_stopThread; 
    HANDLE m_waitThread; 

    FileThread(): m_stopThread(NULL), m_waitThread(NULL) { } 

    static UINT MyThreadProc(LPVOID pParam); 
}; 

FileThread* FileThread::CreateWorkerThread(LPVOID params, UINT priority, UINT flags) 
{ 
    return (FileThread*) AfxBeginThread(FileThread::MyThreadProc, params, priority, 0, flags); 
} 

void FileThread::InitThread() 
{ 
    m_stopThread = CreateEvent(0, TRUE, FALSE, 0); 
    m_waitThread = CreateEvent(0, TRUE, FALSE, 0); 
} 

void FileThread::StopThread() 
{ 
    ::SetEvent(m_stopThread); 
    ::WaitForSingleObject(m_waitThread, INFINITE); 
    ::CloseHandle(m_stopThread); 
    ::CloseHandle(m_waitThread); 
} 


UINT FileThread::MyThreadProc(LPVOID pParam) 
{ 
    ThreadData* pLink = (ThreadData*)pParam; 
    BOOL continueProcess = TRUE; 
    int returnCode = EXITCODE_SUCCESS; 

    while (continueProcess) 
    { 
     if(::WaitForSingleObject(pLink->pMe->GetStopHandle(), 0) == WAIT_OBJECT_0) 
     { 
      ::SetEvent(pLink->pMe->GetWaitHandle()); 
      continueProcess = FALSE; 
     } 

     // the thread is looking for some files... 
    } 

    delete pLink; // it was allocated from the UI thread 

    return returnCode; 
} 

然後,在我啓動線程:

ThreadData * td = new ThreadData(); 

m_myFileThread = FileThread::CreateWorkerThread((LPVOID)td, THREAD_PRIORITY_LOWEST, CREATE_SUSPENDED); 

td->pMe = m_myFileThread; 
m_myFileThread->m_bAutoDelete = FALSE; 

m_myFileThread->InitThread(); 
m_myFileThread->ResumeThread(); 

最後,停止(與crash):

DWORD exitCode; 
if (m_myFileThread != NULL && GetExitCodeThread(m_myFileThread->m_hThread, &exitCode) && (exitCode == STILL_ACTIVE)) 
    { 
     m_myFileThread->StopThread(); 
     if(::WaitForSingleObject(m_myFileThread->m_hThread, 5000) == WAIT_TIMEOUT) 
     { 
      TerminateThread(m_myFileThread->m_hThread, EXITCODE_ABORT); 
     } 
    } 

if (m_myFileThread != NULL) 
{ 
    delete m_myFileThread; // => CRASH 
} 

看來我試圖刪除已經刪除的內容並最終導致堆損壞。我嘗試將m_bAutoDelete設置爲TRUE,而不是通過我得到相同的崩潰來自己刪除線程(當程序試圖調用AfxEndThread時)。

線程終止其線程處理並返回退出代碼。

回答

1

它看起來對我來說,這裏有一個問題:

FileThread* FileThread::CreateWorkerThread(LPVOID params, UINT priority, 
              UINT flags) 
{ 
    return (FileThread*) AfxBeginThread(FileThread::MyThreadProc, params, 
             priority, 0, flags); 
} 

AfxBeginThread返回CWinthread*,所以才鑄造這派生類自己並不使其成爲派生類的一個實例。我很驚訝它的作品。

而不是從CWinThread推導FileThread,最好在包裝類中保存CWinthread*成員變量,並在必要時通過訪問器公開該線程句柄。

+0

下面的MSDN示例顯示瞭如何做正確鑄件 http://msdn.microsoft.com/en-us/library/z2h4xz23.aspx 同樣的CWinThread具有自動刪除機制:HTTP:// MSDN。 microsoft.com/en-us/library/4bbe9bte.aspx – odedsh

+0

@adssh那麼,創建一個UI線程,它有一個消息泵(需要套接字) - 它*可以*用作工作線程,但它可能在許多情況下有點矯枉過正。 –

+2

@Roger Rowland:那是你認爲的那種問題:「我認爲那是愚蠢的?! ;) 非常感謝我將CWinThread包裝在我的課堂中,一切都很好。 已解決的問題 – Jonyjack