thread.join()的超时

ty.*_*ty. 27 c++ c++11

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

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

How*_*ant 22

没有超时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";
}
Run Code Online (Sandbox Code Playgroud)

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

  • @MooingDuck:不是在这种情况下,因为读取或写入的所有`thread_count`都处于锁定状态`m`.因此,使`thread_count`原子是正确的,但多余且不必要的昂贵. (2认同)

Man*_*ork 7

对的,这是可能的.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. --- */

}
Run Code Online (Sandbox Code Playgroud)

但是,这实际上启动了执行该操作的第三个线程thread.join().

(注意:析构函数future将阻塞直到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;
Run Code Online (Sandbox Code Playgroud)

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

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

我在Cygwin上用gcc 4.9.3测试了两个版本.


Sim*_*mon 5

对于 Boost,timed_join() 现在已弃用。使用try_join_for()代替:

myThread.try_join_for(boost::chrono::milliseconds(8000))
Run Code Online (Sandbox Code Playgroud)


Gal*_*lik 5

除了可以显式使用线程外,还可以使用std::async()为您提供a,std::future<>并且可以对std::future:进行定时等待。

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