C++ 在AfxBeginThread创建CWinThread之后,谁拥有它?
我正在使用C++ 在AfxBeginThread创建CWinThread之后,谁拥有它?,c++,mfc,C++,Mfc,我正在使用AfxBeginThread启动一个线程。这将返回指向新CWinThread对象的指针 MSDN声明此指针为NULL,如果线程创建失败,它将取消分配所有内容。但是,只要线程在定期启动后退出,CWinThread对象仍然存在。我不确定是否应该删除CWinThread对象,或者这是由MFC本身完成的(尽管看起来不是这样) 仅供参考,线程不太可能退出,因为它应该一直运行到应用程序结束。但是,由于我使用它作为线程池的一部分,我不希望CWinThread永远挂起aorund。如果线程仍在运行,则
AfxBeginThread
启动一个线程。这将返回指向新CWinThread
对象的指针
MSDN声明此指针为NULL,如果线程创建失败,它将取消分配所有内容。但是,只要线程在定期启动后退出,CWinThread
对象仍然存在。我不确定是否应该删除CWinThread
对象,或者这是由MFC本身完成的(尽管看起来不是这样)
仅供参考,线程不太可能退出,因为它应该一直运行到应用程序结束。但是,由于我使用它作为线程池的一部分,我不希望
CWinThread
永远挂起aorund。如果线程仍在运行,则不应删除它。一旦停止,只需对AfxBeginThread
返回的指针使用运算符delete
,即可释放线程使用的内存:
CWinThread *thread = AfxBeginThread(...);
/* ... */
// now wait for it to terminate
WaitForSingleObject(thread->m_hThread, INFINITE);
delete thread;
您应该存储
CWinThread
指针,直到线程/应用程序结束,以便释放分配给它们的内存。否则,您将出现内存泄漏。我从不相信CWinThread会在其自身之后进行清理。我通常创建线程,并告诉MFC我将进行清理,特别是在程序关闭时:
CWinThread *thread = AfxBeginThread(...);
thread->m_bAutoDelete = FALSE;
但是,您必须保存线程指针,否则会出现内存泄漏。清理CWinThread对象的责任取决于它的m_bautodelet值。默认设置是删除自身。对于fire和forget短时间运行的线程,这很好。它会自行清理的 如果您的线程正在长时间运行,并且需要被告知该退出或以其他方式与之交互,那么您将希望CWinThread句柄保持有效,而不是指向自删除的对象 如果您将m_bAutoDelete设置为FALSE,您将声明对删除它负责。为了安全地使用返回的指针,您应该创建suspended并在恢复之前将其设置为FALSE,正如josephnewmer在其文章中所建议的那样
谢谢你,我刚刚了解了m_bAutoDelete会员的情况,并按照你和@fontanini的建议去做+这个答案是错误的。当此代码尝试设置
m_bAutoDelete
时,CWinThread
对象可能已经删除了自身。请参阅@jla关于如何正确使用此技术的答案。我不同意答案是错误的。答案的关键是m_bAutoDelete,为了简洁起见,样本中的参数to被省略。同样重要的是,CREATE_SUSPENDED,否则,您的评论是正确的。我同意@jila的答案更完整。这是唯一正确的答案。其他两个答案是错误的,可能会导致未定义的行为。如果您有一个m_bAutoDelete=TRUE的GUI线程,并且您观察到尽管用户单击了主窗口的“关闭”按钮,但该线程并未退出,则可能需要在PostNcDestroy()中调用PostQuitMessage()。还请注意,如果您自己在清理线程(m_bAutoDelete=FALSE),您仍然希望在删除对象之前等待线程退出此答案是错误的。线程终止时,CWinThread
将关闭线程句柄并删除自身。因此,此代码可能会在未定义行为的闭合句柄上调用WaitForSingleObject
,也可能会尝试删除已删除的对象。正确的方法是在挂起的线程上使用m_bAutoDelete
,正如@jla在回答中所解释的那样。
thread = AfxBeginThread(proc, this,
THREAD_PRIORITY_NORMAL, // default: use it
0, // default stack size
CREATE_SUSPENDED); // let us set auto delete
if(thread) { // protect against that rare NULL return
thread->m_bAutoDelete = FALSE;
thread->ResumeThread();
}