如何等待几个 std::threads

Posted

技术标签:

【中文标题】如何等待几个 std::threads【英文标题】:How to wait for several std::threads 【发布时间】:2016-03-03 15:59:44 【问题描述】:

基于这个问题:Timeout for thread.join()(ManuelAtWork 的回答)我尝试为我的 std::threads 实现超时:

std::vector<std::shared_ptr<TestFlow>> testFlowObjects;
std::thread workerThreads[MAX_PARALLEL_NR]; // maximum of 32 threads
std::vector<std::future<void>> helperThreads;

for(int readerCounter=0; readerCounter<GetNumberOfReader(); readerCounter++)

    testFlowObjects.push_back(std::make_shared<TestFlow>(m_logFiles));

    testFlowObjects.back()->SetThreadID(readerCounter);
    testFlowObjects.back()->SetTestResults(m_testResultsVector); // vector of int
    workerThreads[readerCounter] = std::thread(&TestFlow::DoWork, testFlowObjects.back());


// wait for all threads
for(int threadCount=0; threadCount<GetNumberOfReader(); threadCount++)

    // use helper threads to be able to join with timeout
    helperThreads.push_back(std::async(std::launch::async, &std::thread::join, &workerThreads[threadCount]));
    helperThreads.back().wait_for(std::chrono::seconds(5)); // 5 sec

如果我使用连接而不是 std::future 辅助线程代码,它可以正常工作,但我不能等待无限!

使用 std::future 方法,似乎并非所有线程都已完成,我得到了:R6010: abort() has been called

任何想法如何正确地做到这一点?

我想我必须像这样改变它:

if(helperThreads.back().wait_for(std::chrono::seconds(5)) == std::future_status::timeout) // WHAT SHOULD I DO HERE???

【问题讨论】:

我猜这不是你说的版本?你在哪里加入你的workerThreads?期货的目的是什么? 展示一个完整的例子。你加入了工作线程吗?为什么要在循环中等待 5 秒,这有什么意义?这意味着您甚至在启动下一个任务之前都要等待。当然,您要启动所有任务,然后等待它们。当你只等待std::future 对象时,你为什么要问等待std::thread @JonathanWakely 如果我加入线程,它会等到线程完成,但我必须在定义的时间后退出(5 秒仅用于测试 -> 没有任何实际意义)你读过 ManuelAtWork 的答案吗?他的方法使用辅助线程来完成工作线程,但我必须使其适应多个线程(看我的示例)! @Superlokkus 你读过这个问题吗?一切都被描述了,我不明白你为什么反对它?! (发布更多代码没有帮助) 但是你在循环中执行helperThreads.back().wait_for(std::chrono::seconds(5)); inside,所以你启动一个新线程等待更早的线程,然后等待 5 秒,然后启动另一个线程,然后等待5 秒,然后启动另一个线程,然后等待 5 秒……这意味着您总共等待 5 x GetNumberOfReader 秒!您是否查看了其他问题的已接受答案? 【参考方案1】:

简而言之和推荐

您发布的方法(ManuelAtWork 的回答)是一种变通方法,使用 std::future 的等待通信语义作为在 std::thread::join 上等待超时的方法。这也可以通过 条件变量 的通信来实现,正如所提到的公认答案。 但是,为什么要在单独的 std::thread 中开始 ThreadFunc 呢?只需使用std::async,它将返回一个未来,它将执行您的ThreadFunci.e。 TestFlow::DoWork

您可能会因为尝试加入不可加入的线程而中止,或者因为您没有在该位置加入一些明确的(移动新线程时,在旧std::thread 的析构函数中)

workerThreads[readerCounter] = std::thread(&TestFlow::DoWork, testFlowObjects.back());

背景/问题

如果您仍想使用std::thread,您必须自己进行线程之间的通信和等待。这意味着许多类型的任务和问题(停止、加入、等待、线程池)。 您链接的解决方法假设您有一些其他方法可以终止线程。 (通过沟通)

【讨论】:

以上是关于如何等待几个 std::threads的主要内容,如果未能解决你的问题,请参考以下文章

在返回位置之前如何等待计时器?

如何在 C# 中等待单个事件,带有超时和取消

如何让程序等待X秒并允许UI执行?

如何使用 JFoenix 等待显示下一个 toast (snackBar)

如何在调用WS之前等待某事

如何实现一个等待元素弹出的堆栈