C++ thread.join() 超时

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9948420/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:25:13  来源:igfitidea点击:

Timeout for thread.join()

c++c++11

提问by ty.

Is it possible to set a timeout for a call to std::thread::join()? I want to handle the case in which the thread is taking too long to run, or terminate the thread. I may be doing this for multiple threads (say, up to 30).

是否可以为呼叫设置超时std::thread::join()?我想处理线程运行时间过长的情况,或者终止线程。我可能会为多个线程执行此操作(例如,最多 30 个)。

Preferably without boost, but I'd be interested in a boost solution if that's the best way.

最好没有提升,但如果这是最好的方法,我会对提升解决方案感兴趣。

采纳答案by Howard Hinnant

There is no timeout for std::thread::join(). However you can view std::thread::join()as merely a convenience function. Using condition_variables you can create very rich communication and cooperation between your threads, including timed waits. For example:

没有超时std::thread::join()。但是,您可以std::thread::join()仅将其视为一种便利功能。使用condition_variables 您可以在线程之间创建非常丰富的通信和合作,包括定时等待。例如:

#include <chrono>
#include <thread>
#include <iostream>

int thread_count = 0;
bool time_to_quit = false;
std::mutex m;
std::condition_variable cv;

void f(int id)
{
    {
    std::lock_guard<std::mutex> _(m);
    ++thread_count;
    }
    while (true)
    {
        {
        std::lock_guard<std::mutex> _(m);
        std::cout << "thread " << id << " working\n";
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(250));
        std::lock_guard<std::mutex> _(m);
        if (time_to_quit)
            break;
    }
    std::lock_guard<std::mutex> _(m);
    std::cout << "thread ended\n";
    --thread_count;
    cv.notify_all();
}

int main()
{
    typedef std::chrono::steady_clock Clock;
    std::thread(f, 1).detach();
    std::thread(f, 2).detach();
    std::thread(f, 3).detach();
    std::thread(f, 4).detach();
    std::thread(f, 5).detach();
    auto t0 = Clock::now();
    auto t1 = t0 + std::chrono::seconds(5);
    std::unique_lock<std::mutex> lk(m);
    while (!time_to_quit && Clock::now() < t1)
        cv.wait_until(lk, t1);
    time_to_quit = true;
    std::cout << "main ending\n";
    while (thread_count > 0)
        cv.wait(lk);
    std::cout << "main ended\n";
}

In this example mainlaunches several threads to do work, all of which occasionally check if it is time to quit under a mutex (this could also be an atomic). The main thread also monitors if it is time to quit (if the threads get all their work done). If main runs out of patience, he just declares it to be time to quit, then waits for all threads to perform any necessary clean up before exiting.

在这个例子中,main启动了几个线程来完成工作,所有这些线程偶尔会检查是否是时候在互斥锁下退出(这也可能是一个原子)。主线程还监视是否该退出(如果线程完成所有工作)。如果 main 没有耐心,他只是宣布是时候退出了,然后在退出之前等待所有线程执行任何必要的清理。

回答by ManuelAtWork

Yes, it is possible. The solution that has been suggested by Galik looks like this:

对的,这是可能的。Galik 建议的解决方案如下所示:

#include <thread>
#include <future>
...
// Launch the thread.
std::thread thread(ThreadFnc, ...);
...
// Terminate the thread.
auto future = std::async(std::launch::async, &std::thread::join, &thread);
if (future.wait_for(std::chrono::seconds(5)) 
    == std::future_status::timeout) {

  /* --- Do something, if thread has not terminated within 5 s. --- */

}

However, this essentially launches a third thread that performs the thread.join().

但是,这实际上会启动第三个线程来执行thread.join().

(Note: The destructor of futurewill block until threadhas joined and the auxiliary thread has terminated.)

(注意:futurewill的析构函数会阻塞直到thread加入并且辅助线程终止。)



Maybe launching a thread just to bring another thread down is not what you want. There is another, portable solution without an auxiliary thread:

也许启动一个线程只是为了降低另一个线程不是您想要的。还有另一种没有辅助线程的便携式解决方案:

#include <thread>
#include <future>
...
// Launch the thread.
std::future<T_return>*  hThread 
  = new std::future<T_return>(std::async(std::launch::async, ThreadFnc, ...));
...
// Terminate the thread.
if (hThread->wait_for(std::chrono::seconds(5)) 
    == std::future_status::timeout) {

  /* --- Do something, if thread has not terminated within 5 s. --- */

} else
  delete hThread;

where T_returnis the return type of your thread procedure. This scenario uses an std::future/ std::asynccombination instead of an std::thread.

T_return线程过程的返回类型在哪里。此方案使用std::future/std::async组合而不是std::thread.

Note that hThreadis a pointer. When you call the deleteoperator on it, it will invoke the destructor of *hThreadand block until the thread has terminated.

请注意,这hThread是一个指针。当你调用delete它的操作符时,它会调用*hThread和阻塞的析构函数,直到线程终止。

I have tested both versions with gcc 4.9.3 on Cygwin.

我已经在 Cygwin 上用 gcc 4.9.3 测试了这两个版本。

回答by Galik

Instead of using threads explicitly you can use std::async()to provide you with a std::future<>and you can do timed waits on the std::future:

您可以使用std::async()来为您提供 a std::future<>,而不是显式使用线程,您可以对 进行定时等待std::future

http://en.cppreference.com/w/cpp/thread/future/wait_for

http://en.cppreference.com/w/cpp/thread/future/wait_for

回答by Simon

timed_join() is now deprecated. Use try_join_for() instead:

timed_join() 现在已弃用。使用 try_join_for() 代替:

myThread.try_join_for(boost::chrono::milliseconds(8000))

回答by user1202136

For Boost, see timed_join() for the version of join() with timeout.

对于 Boost,请参阅timed_join() 以获取带有超时的 join() 版本。