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

why t.join cannot be called twice in this example?

一段时间以来,我一直在尝试使用 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 具有 post 条件

joinable() is false

并处于错误状态

invalid_argument if joinable() is 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 以防你想要一个也 returns 值的异步函数。