2014-01-20 107 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