为什么 t.join 在这个例子中不能被调用两次?

问题描述

一段时间以来,我一直在尝试使用 std::thread,在我的项目中,我想确保线程不会一次做一件事,这就是我尝试制作一个简单项目的原因有类似“检查”线程是否完成的东西,然后重新开始

#include <future>
#include <thread>
#include <chrono>
#include <iostream>
using namespace std::chrono_literals;

void Thing() 
{
    std::this_thread::sleep_for(3s);
}
int main() 
{
    std::packaged_task<void()> task(Thing);
    auto future = task.get_future();

    std::thread t(std::move(task));

    while (true) {
        auto status = future.wait_for(0ms);

        if (status != std::future_status::ready) 
        {
            std::cout << "not yet" << std::endl;
        }
        else
        {
            t.join();
            std::cout << "Join()" << std::endl;
        }
        std::this_thread::sleep_for(300ms);
    }
}

使用此代码时,我在 std::cout << "Join()" << std::endl; 行出现错误错误显示Unhandled exception at 0x7632A842 in dasd.exe: Microsoft C++ exception: std::system_error at memory location 0x00AFF8D4. 当线程准备好并调用 t.join() 时会出现此错误

这个项目的输出

not yet

...

not yet
Join()

提前致谢

解决方法

如你所见https://en.cppreference.com/w/cpp/thread/thread/join

join 具有作为后置条件

joinable() 为假

并且处于错误状态

invalid_argument if joinable() 为 false

所以你不能两次调用它。

您可能希望在调用 join 或重写循环后中断循环,例如:

while (future.wait_for(300ms) != std::future_status::ready) {
    std::cout << "not yet" << std::endl;
}
t.join();
std::cout << "Join()" << std::endl;
,

实际上,您不需要 while 循环。相反,您可以简单地调用 join

join 的作用是等待线程完成其工作。线程完成其工作后,它退出并清理堆栈,第二次调用 join 完全没有意义。

我还建议您使用 std::async,以防您想要一个也返回值的异步函数。