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

如何让线程等待含内部线程的对象完成析构?

嘿,我来帮你搞定这个gTest里的线程时序问题!咱们一步步拆解:

首先,揪出一个容易踩的C++语法陷阱

你写的 DummyClass Obj(); 根本不是创建DummyClass对象,而是声明了一个名叫Obj、返回值为DummyClass的函数!这就导致你后续调用Obj.Func1(...)的逻辑完全不符合预期(说不定你的编译器没报错是因为有其他同名函数?)。正确的对象创建方式应该是:

DummyClass Obj;  // 无参构造创建对象
// 或者C++11及以上用
DummyClass Obj{};

这是很多C++开发者都会踩的坑,先把这个修正了,咱们再解决核心的线程等待问题。

核心问题:让service等DummyClass线程完全退出再停止

你现在用usleep是靠碰运气的延迟,完全不可靠——不同环境下线程执行速度不一样,延迟加少了还是会出问题,加多了又浪费时间。咱们用显式的生命周期控制+正确的线程停止逻辑来替代:

1. 确保SasThreadHelper的线程能正确响应停止信号

你的StopThread方法里设置了m_stop_sas_thread_flag然后调用join(),但关键是ReadMessagesFromQueue函数必须周期性检查这个停止标志,一旦标志置位就立刻退出。举个例子,如果你的线程是处理队列消息,应该这么写:

void SasThreadHelper::ReadMessagesFromQueue() {
    while (!m_stop_sas_thread_flag) {
        // 如果是阻塞式读取队列,要确保能被唤醒检查停止标志
        std::unique_lock<std::mutex> lock(m_queue_mutex);
        // 等待队列有消息,或者收到停止信号
        m_cv.wait(lock, [this](){ 
            return !m_message_queue.empty() || m_stop_sas_thread_flag; 
        });
        
        // 收到停止信号就直接退出
        if (m_stop_sas_thread_flag) break;
        
        // 处理队列消息的逻辑
        auto msg = m_message_queue.front();
        m_message_queue.pop();
        lock.unlock();
        
        // 执行消息处理(比如发请求给service)
    }
}

另外,m_stop_sas_thread_flag必须是线程安全的!多个线程读写这个变量时,要用std::atomic<int>来声明,避免内存可见性问题:

std::atomic<int> m_stop_sas_thread_flag = 0;

如果你的线程函数里没检查这个标志,哪怕调用了StopThread,线程也会继续跑,甚至join()会一直阻塞,这肯定会导致时序混乱。

2. 显式控制DummyClass的生命周期,让它先于service停止

你当前的测试代码里,DummyClass对象(如果正确创建的话)是局部变量,它的析构会在service->Stop()之后(函数结束时才会析构局部变量),这和你想要的「service等对象析构完再停止」完全相反!

咱们用作用域大括号把对象包裹起来,让它在service->Stop()之前就完成析构:

TEST_F(TestFixture, TestName) {
    service->start(); // 启动service的线程

    {
        // 把DummyClass对象放在这个作用域里
        DummyClass Obj;
        EXPECT_CALL(*_Mock, Func(NotNull(), NotNull(), NotNull(), NotNull(), NotNull(), NotNull()))
            .Times(1)
            .WillRepeatedly(Return(1));
        EXPECT_EQ(true, Obj.Func1(a,b, c, d).IsOk());
    } // 到这里,Obj会被析构!SasThreadHelper的析构函数会调用StopThread,等待线程完全退出

    // 现在DummyClass的线程已经彻底退出了,再停止service
    service->Stop();
}

这样一来,不用usleep也能保证时序:service只会在DummyClass的线程完全结束后才停止,自然不会出现Connection refused(错误码111)的问题——这个错误本质就是service已经停了,但DummyClass的线程还在尝试连接/发请求。

最后再确认下

错误码111的根源就是时序混乱:service先停了,DummyClass的线程还在跑,尝试连接已经关闭的服务端口。按照上面的步骤修正后,这个问题应该就能解决了。

内容的提问来源于stack exchange,提问作者Mohit Chandak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:40:37