CWinThread 由 AfxBeginThread 创建后谁拥有它?

Posted

技术标签:

【中文标题】CWinThread 由 AfxBeginThread 创建后谁拥有它?【英文标题】:Who owns CWinThread after it was created by AfxBeginThread? 【发布时间】:2012-03-15 16:12:00 【问题描述】:

我正在使用AfxBeginThread 启动一个线程。这将返回一个指向新 CWinThread 对象的指针。

MSDN 声明此指针为 NULL,如果线程创建失败,它将释放所有内容。但是,一旦线程在定期启动后退出,CWinThread 对象仍然存在。我不确定我是否应该删除 CWinThread 对象,或者这是否由 MFC 本身完成(尽管看起来并非如此)。

仅供参考,线程不太可能退出,因为它应该一直运行到应用程序结束。但是,由于我将其用作线程池的一部分,因此我不希望 CWinThread 永远挂起 aorund。

【问题讨论】:

【参考方案1】:

清理 CWinThread 对象的责任取决于它的 m_bAutoDelete 值。默认是删除自身。对于火灾并忘记短期运行的线程,这很好。它会自行清理。

如果您的线程长时间运行并且需要被告知是时候退出或与之交互,您将希望 CWinThread 句柄保持有效并且不指向自删除对象。

如果您将 m_bAutoDelete 设置为 FALSE,则您声明对删除它负责。为了安全地使用返回的指针,您应该按照 Joseph Newcomer 在他的Using Worker Threads 文章中的建议创建暂停并将其设置为 FALSE,然后再恢复。

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

【讨论】:

这是唯一正确的答案。其他两个答案是错误的,可能会导致未定义的行为。 如果您有一个 m_bAutoDelete = TRUE 的 GUI 线程,并且您观察到尽管用户单击了主窗口的“关闭”按钮,但该线程并未退出,则可能需要调用 PostQuitMessage()在 PostNcDestroy() 中。 另请注意,如果您自己在线程之后进行清理 (m_bAutoDelete = FALSE),您仍需要等待线程退出后再删除对象【参考方案2】:

我从不相信 CWinThread 会自行清理。我通常会创建线程并告诉 MFC 我会进行清理,特别是在程序关闭时:

CWinThread *thread = AfxBeginThread(...); 
thread->m_bAutoDelete = FALSE;

但是,您必须保存线程指针,否则您会出现内存泄漏。

【讨论】:

谢谢,我刚刚发现了 m_bAutoDelete 成员,并按照您和@fontanini 的建议进行操作。 +1 这个答案是错误的。当这段代码尝试设置m_bAutoDelete 时,CWinThread 对象可能已经自己删除了。请参阅@jla 关于如何正确使用此技术的回答。 我不同意答案是错误的。答案的关键是 m_bAutoDelete,为简洁起见,示例中的参数为“...”。 CREATE_SUSPENDED 也很重要,如果不是,您的评论是正确的。我同意@jila 的回答更完整。【参考方案3】:

如果您的线程仍在运行,则不应删除它。停止后,只需在 AfxBeginThread 返回的指针上使用运算符 delete 即可释放线程使用的内存:

CWinThread *thread = AfxBeginThread(...);
/* ... */
// now wait for it to terminate
WaitForSingleObject(thread->m_hThread, INFINITE); 
delete thread;

您应该存储CWinThread 指针直到您的线程/应用程序结束,以便您可以释放为它们分配的内存。否则会出现内存泄漏。

【讨论】:

这个答案是错误的。在线程终止时,CWinThread 将关闭线程句柄,并删除自己。因此,此代码可能会在关闭的句柄上调用WaitForSingleObject,这是未定义的行为,或者它可能会尝试删除已被删除的对象。正确的方法是在 suspended 线程上使用m_bAutoDelete,正如@jla 的回答中所解释的那样。

以上是关于CWinThread 由 AfxBeginThread 创建后谁拥有它?的主要内容,如果未能解决你的问题,请参考以下文章

CWinThread 消息映射

如何使用 CWinThread 在 MFC 中创建工作线程?

CWinThread 查询 (MFC)

帮助在 MFC 中使用 CWinThread

如何在 CWinThread 派生类中正确创建 CDialog 框

是否可以在基于对话框的应用程序中从 CWinThread 类派生类