将asio::work移至类后,io_context.run无法维持程序运行求助
异步TCP客户端维持连接问题排查与解决
问题场景
此前在main函数中使用asio::work配合线程维持io_context.run()不退出是可行的,但将worker和线程逻辑移至kenyence_client类中后,程序执行完会自动退出,无法在无消息收发时保持TCP连接,最终会打印"flinish"后结束进程。
核心原因
- main线程提前退出:
main函数执行到return 0时,kenyence_ptr会被销毁,触发类的析构函数。析构函数中调用了stopTcpCommuncation(),会直接调用io_context.stop()并join线程,强制终止IO上下文和工作线程,导致连接断开。 - worker生命周期与类绑定:
asio::io_context::work是类的成员变量,当kenyence_ptr被销毁时,worker也会随之销毁,io_context失去工作保持项,run()会在所有pending操作完成后返回,线程自然退出。 - 缺乏线程等待逻辑: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
相关产品推荐
相关产品推荐

