如何将std::jthread的stop_token传递给作为线程入口的函数对象
报错原因
你遇到的编译错误本质是std::jthread的stop_token自动注入规则和成员函数调用的参数顺序不匹配:
- 成员函数的第一个隐式参数永远是
this指针,你给operator()加的std::stop_token实际上是第二个参数 std::jthread的规则是:如果传入的可调用对象第一个参数接受std::stop_token类型,才会自动把内部关联的stop_token作为第一个参数注入到调用参数列表里
你之前传入的是成员函数指针&Test::operator()+&test(作为this参数),这种情况下jthread注入的stop_token会插到参数列表最前面,最终调用的参数顺序变成(stop_token, &test),和成员函数要求的(this, stop_token)顺序完全不匹配,因此编译失败。
另外你之前无参版本无法响应停止请求的原因也很简单:你循环里用的token没有和jthread内部的stop_source绑定,调用request_stop()根本不会修改这个token的状态,循环自然不会退出。
解决方法
有两种常用的修复方案,任选一种即可:
方案1:直接传递Test对象作为可调用对象
std::jthread可以直接识别重载了operator()的类对象,自动匹配带std::stop_token的调用签名,不需要手动传成员函数指针和this指针:
// 创建线程的代码直接修改即可 my_thrd = std::make_shared<std::jthread>(test);
这个方案最简单,代码改动量最小。
方案2:用lambda包装成员函数调用
如果你需要保留手动传成员函数的写法,可以用lambda做一层包装,显式接收jthread注入的stop_token再传给operator():
my_thrd = std::make_shared<std::jthread>([&test](std::stop_token token) { test(std::move(token)); });
这个方案灵活性更高,适合需要额外处理参数的场景。
修改完成后调用my_thrd->request_stop()即可正常触发线程停止逻辑。
内容的提问来源于stack exchange,提问作者Ender
相关产品推荐
相关产品推荐

