You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++/MFC中创建std::thread触发ucrtbase.dll异常求助

问题原因

你遇到的异常是因为在OnInitDialog中创建的std::thread对象th1是局部变量,当OnInitDialog执行完毕后,该局部变量会被销毁。此时线程仍处于可连接(joinable)状态,std::thread的析构函数会调用std::terminate()终止程序,这就是ucrtbase.dll抛出异常的根源。控制台项目中程序生命周期较短,主线程结束后整个进程直接退出,不会触发这个析构问题,所以能正常运行。

解决方案

有两种可行的解决方式:

方式一:将线程对象保存为对话框类成员

把std::thread声明为对话框类的成员变量,避免局部变量销毁导致的问题:

  1. 修改对话框头文件CWatchDogPI336Dlg.h,添加成员变量:
#include <thread>

class CWatchDogPI336Dlg : public CDialogEx
{
    // 其他已有成员...
private:
    std::thread m_reloadThread;
};
  1. 修改OnInitDialog代码:
BOOL CWatchDogPI336Dlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    m_reloadThread = std::thread(ReloadWatchdog::Reload);

    return TRUE;
}
  1. 在对话框销毁时合理处理线程,可在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 12:57:37