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();
   }