Cpp Rest SDK HTTP长连接客户端断开后如何终止阻塞线程
解决Cpp Rest SDK SSE服务器客户端断开后线程阻塞的问题
问题根源
Cpp Rest SDK的http_listener默认不会在客户端断开连接时自动取消未完成的异步操作,导致你在wReplyTask.wait()处永久阻塞,占用线程池资源(默认上限40)。
具体解决方案
监听连接关闭事件
每个请求的响应对象可以绑定on_close回调,当客户端主动断开时触发,在回调中取消对应的异步推送任务。替换阻塞式
wait()为异步任务链
避免用wait()阻塞线程,改用pplx::task的异步链式调用,配合取消机制让线程能正常回收。
示例代码
void handleGet(http_request request) { // 构造SSE响应头 auto response = request.create_response(status_codes::OK); response.headers().add(U("Content-Type"), U("text/event-stream")); response.headers().add(U("Cache-Control"), U("no-cache")); response.headers().add(U("Connection"), U("keep-alive")); pplx::task<void> pushTask; // 绑定连接关闭回调,触发时取消推送任务 auto closeRegistration = response.on_close([&pushTask]() { pushTask.cancel(); }); // 异步执行事件推送逻辑 pushTask = pplx::create_task([&response]() { try { while (true) { // 生成SSE格式数据 std::wstring sseData = U("data: new event\n\n"); response.write(to_string_t(sseData)); // 等待期间允许被取消 pplx::wait(1000).wait(); } } catch (const pplx::task_canceled&) { // 捕获取消异常,正常退出循环 } }); // 异步完成响应,避免阻塞线程 response.complete().then([closeRegistration](pplx::task<void> t) { try { t.get(); } catch (const std::exception& e) { // 处理响应完成时的异常 } }); }
额外注意事项
- 所有异步任务必须能被正确取消,确保线程不会被永久占用
- 不要在请求处理函数中使用阻塞式调用,尽量用
then()回调处理后续逻辑,让SDK线程池高效复用线程 - 可以维护一个全局的客户端连接集合,在
on_close回调中移除对应条目,方便统一管理活跃连接
内容的提问来源于stack exchange,提问作者mikebar84
相关产品推荐
相关产品推荐

