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

将asio::work移至类后,io_context.run无法维持程序运行求助

异步TCP客户端维持连接问题排查与解决

问题场景

此前在main函数中使用asio::work配合线程维持io_context.run()不退出是可行的,但将worker和线程逻辑移至kenyence_client类中后,程序执行完会自动退出,无法在无消息收发时保持TCP连接,最终会打印"flinish"后结束进程。

核心原因

  1. main线程提前退出:main函数执行到return 0时,kenyence_ptr会被销毁,触发类的析构函数。析构函数中调用了stopTcpCommuncation(),会直接调用io_context.stop()并join线程,强制终止IO上下文和工作线程,导致连接断开。
  2. worker生命周期与类绑定:asio::io_context::work是类的成员变量,当kenyence_ptr被销毁时,worker也会随之销毁,io_context失去工作保持项,run()会在所有pending操作完成后返回,线程自然退出。
  3. 缺乏线程等待逻辑:main线程没有等待客户端的工作线程完成,直接结束进程,导致所有子线程被强制终止。

解决方案

修改点1:让main线程阻塞等待

在main函数的return 0前添加阻塞逻辑,避免main线程提前退出,保证kenyence_client对象和工作线程持续运行。例如:

std::cout << "flinish\n";
// 等待用户输入触发退出,或等待工作线程结束
std::cin.get();
// 当需要退出时再手动调用停止接口
// kenyence_ptr->stopTcpCommuncation();

return 0;

修改点2:调整析构函数逻辑

移除析构函数中自动调用stopTcpCommuncation()的逻辑,改为由用户手动触发停止操作,避免对象销毁时强制终止IO上下文:

kenyence_client::~kenyence_client() 
{
    std::cout << "Is in distructer\n";
    if (workingThread_.joinable()) 
    {
        workingThread_.join();
    }
    // 移除自动停止逻辑,由用户主动调用stopTcpCommuncation()
}

修改点3:添加线程等待接口(可选)

为kenyence_client类添加wait()方法,让main线程可以等待所有工作线程完成:

  • 在client.h的public区域添加:
void wait();
  • 在client.cpp中实现:
void kenyence_client::wait()
{
    if (workingThread_.joinable())
        workingThread_.join();
    if (ioContextThread_.joinable())
        ioContextThread_.join();
}
  • 在main函数中调用:
std::cout << "flinish\n";
kenyence_ptr->wait(); // 等待所有工作线程结束
return 0;

修改点4:确保worker持续有效

只要kenyence_client对象在main线程中保持存活,类成员worker_就会持续让io_context有工作保持项,run()不会无理由返回。因此要避免kenyence_ptr在main线程中提前被销毁。

验证效果

修改后,程序执行完消息发送逻辑后会进入阻塞状态,不会自动退出,TCP连接会持续保持;当用户输入触发退出或手动调用stopTcpCommuncation()后,才会终止IO上下文并结束进程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 04:25:01