C++/MFC中创建std::thread触发ucrtbase.dll异常求助
问题原因
你遇到的异常是因为在OnInitDialog中创建的std::thread对象th1是局部变量,当OnInitDialog执行完毕后,该局部变量会被销毁。此时线程仍处于可连接(joinable)状态,std::thread的析构函数会调用std::terminate()终止程序,这就是ucrtbase.dll抛出异常的根源。控制台项目中程序生命周期较短,主线程结束后整个进程直接退出,不会触发这个析构问题,所以能正常运行。
解决方案
有两种可行的解决方式:
方式一:将线程对象保存为对话框类成员
把std::thread声明为对话框类的成员变量,避免局部变量销毁导致的问题:
- 修改对话框头文件
CWatchDogPI336Dlg.h,添加成员变量:
#include <thread> class CWatchDogPI336Dlg : public CDialogEx { // 其他已有成员... private: std::thread m_reloadThread; };
- 修改
OnInitDialog代码:
BOOL CWatchDogPI336Dlg::OnInitDialog() { CDialogEx::OnInitDialog(); m_reloadThread = std::thread(ReloadWatchdog::Reload); return TRUE; }
- 在对话框销毁时合理处理线程,可在
OnDestroy中添加:
void CWatchDogPI336Dlg::OnDestroy() { CDialogEx::OnDestroy(); if (m_reloadThread.joinable()) { // 无需等待线程结束则用detach(),需要等待则用join() m_reloadThread.detach(); } }
方式二:直接detach线程
创建线程后立即调用detach(),让线程与主线程分离,线程对象销毁时不会触发终止逻辑:
BOOL CWatchDogPI336Dlg::OnInitDialog() { CDialogEx::OnInitDialog(); std::thread th1(ReloadWatchdog::Reload); th1.detach(); // 添加此行 return TRUE; }
额外注意事项
- 如果
call_method()涉及MFC控件或UI操作,必须通过Invoke或SendMessage切换到UI线程执行,MFC的UI对象不允许在非主线程直接访问,否则会引发其他异常。 - 无限循环的线程要添加退出机制,比如设置全局或成员变量作为终止标志,避免程序退出时线程无法正常结束。
内容的提问来源于stack exchange,提问作者Teppei Abe
相关产品推荐
相关产品推荐

