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 在 MFC 中创建工作线程?