如何检查一个已分离的std::thread是否仍在运行?

3

对于一个分离线程,我们无法使用 joinable() 函数,使用布尔变量似乎也不是正确的方式。有没有一种方法可以检查分离线程是否仍然活着并正在运行?


2
为什么在需要知道状态时要将其分离? - slawekwin
1
你不应该在第一时间分离线程。这类似于使用 const_cast - user7860670
1
“Thread is finished/still running” 这是一个毫无意义的信息。你关心的是“线程是否完成了它的工作”。这就是条件变量的作用。 - n. m.
3
“joinable”并不意味着“已完成”。 - n. m.
1
@PrashantShubham 套接字可以是非阻塞的... - Galik
显示剩余10条评论
2个回答

4

有几种方法可以解决这个问题。如果您坚持使用线程,则可以使用std::future<void>来检测其何时退出:

std::promise<void> promised_thread_exit;

std::future<void> thread_exited = promised_thread_exit.get_future();

std::thread(
  [] (std::promise<void> promised_thread_exit)
  {
    promised_thread_exit.set_value_at_thread_exit();
    DoBackgroundWork();
  },
  std::move(promised_thread_exit));
thread.detach();

// later...
thread_exited.get();

然而,这似乎是很多工作。 std::thread 是一种相当底层的原语。 如果目标只是在后台执行一些工作,则 std::async 是更好的选择:

std::future<void> work_complete = std::async(std::launch::async, DoBackgroundWork());

// later...
work_complete.get();

无论哪种情况,如果您需要在不阻塞的情况下检查工作状态,可以通过等待超时为0的future来实现:

using namespace std::chrono_literals;

//...

if (work_complete.wait_for(0s) == std::future_status::ready)
{
  // work has finished
}

话虽如此,像这样检查状态通常是不必要的。如果看起来需要,那么您应该考虑是否有更简单的替代方案。


所有这些都将会阻塞,就像 thread::join 一样。问题在于如何检查工作是否已经完成,而不是等待工作完成。 - n. m.
如果需要,您可以对std::future进行非阻塞检查,等待超时为0。 (在未来 - 没有双关语 - 我们将拥有is_ready方法。)但一般来说,我们只有两个原因想要检查线程是否完成:(1)查看结果是否准备好以便我们可以使用它,或者(2)在取消后进行清理。 std :: future很好地处理了这两种情况。 - Peter Ruderman
是的,但也许你希望这在答案中。 - n. m.
我已经更新了答案,但是我不确定 OP 是否想要这样做。他的问题似乎是他想在一个函数中开始异步工作,但不知道如何在函数外等待该工作完成。 - Peter Ruderman

0
你可以使用 std::condition_variable 来在分离的线程完成时通知主线程:
#include <iostream>
#include <mutex>
#include <thread>

int main()
{
    std::mutex mutex;
    std::condition_variable cv;

    std::thread t([&]() {
        std::cout << "Wait" << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));

        std::unique_lock<std::mutex> lock(mutex);
        std::cout << "Thread end" << std::endl;

        cv.notify_all();
    });

    t.detach();

    std::unique_lock<std::mutex> lock(mutex);
    cv.wait(lock);

    std::cout << "Main end" << std::endl;

    return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接