我有一个多线程应用程序,循环等待用户输入作为主线程。 在正确的输入上,它应该停止循环并等待所有其他线程,以正确结束。
为此,我创建了一个 std :: list ,其中我为创建线程创建了 std :: future 对象
std::list<std::future<int>> threads;
threads.emplace_front(std::async(std::launch::async, ...));
我的印象是,让 list 超出范围,应该阻塞,直到所有线程返回其主函数,因为 list 的析构函数将会破坏所有 std :: future 元素和the destructor of those将等待,以便线程完成。
编辑:由于相关,我会在此处添加: 这是在Win7上使用Visual Studio 2013 Professional中的MSVC版本 的 /修改
当我尝试这个时,它没有阻止,我不得不添加
for (auto it = threads.begin(); it != threads.end(); ++it) {
it->get();
}
到函数的末尾,要正确阻塞。
我是否错过了解某些内容,或者我是否必须以不同的方式创建该主题,以便做我想做的事情?
答案 0 :(得分:13)
这是一个MSVC bug that has been fixed,但是在MS发布新版本的Visual C ++之前,修复程序将无法使用,可能在2015年的某个时候。(它也是available in the CTP for the new version,但是它很糟糕将其用于任何生产代码的想法...)
正如Scott Meyers在his blog post中解释的那样,使用std::future
策略的std::async
调用返回的launch::async
的析构函数需要阻塞,直到生成的线程完成执行(§30.6.8[futures.async] / p5):
如果实施选择
launch::async
政策,
- [...]
- 关联的线程完成与(1.10)同步 从成功检测到就绪的第一个函数返回 共享状态的状态或从最后一个函数返回的状态 释放共享状态,以先发生者为准。
在这种情况下,future
的析构函数是“释放共享状态的最后一个函数”,因此线程完成必须与同步(即,之前发生)返回那个功能。
答案 1 :(得分:0)
我查看了std :: future的文档,发现这是std :: future的析构函数:
释放任何共享状态。这意味着
注意最后一点。在我看来,你必须在范围的最后调用get
。