在for循环中使用std :: async和launch :: async时,我的代码在同一个线程中串行运行,就好像每个异步调用在启动之前等待前一个异步调用一样。在std :: async引用(std::async)的注释中,如果std :: future未绑定到引用,则可以这样做,但我的代码不是这种情况。任何人都可以找出它为什么连续运行?
这是我的代码段:
class __DownloadItem__ { //DownloadItem is just a "typedef shared_ptr<__DownloadItem__> DownloadItem"
std::string buffer;
time_t last_access;
std::shared_future<std::string> future;
}
for(uint64_t start: chunksToDownload){
DownloadItem cache = std::make_shared<__DownloadItem__>();
cache->last_access = time(NULL);
cache->future =
std::async(std::launch::async, &FileIO::download, this, api,cache, cacheName, start, start + BLOCK_DOWNLOAD_SIZE - 1);
}
}
未来将存储在共享的未来,因为多个线程可能正在等待同一个未来。
我也在使用GCC 6.2.1进行编译。
答案 0 :(得分:5)
析构函数中std::future
块返回的async
。这意味着当您到达}
for(uint64_t start: chunksToDownload){
DownloadItem cache = std::make_shared<__DownloadItem__>();
cache->last_access = time(NULL);
cache->future =
std::async(std::launch::async, &FileIO::download, this, api,cache, cacheName, start, start + BLOCK_DOWNLOAD_SIZE - 1);
} // <-- When we get here
cache
被销毁,后者又调用future
的析构函数来等待线程完成。
您需要做的是将future
返回的每个async
存储在for循环之外声明的单独的持久future
中。
答案 1 :(得分:1)
这是C ++ 11定义的std::async
的错误。它的未来&#39;析构函数是特殊的,等待操作完成。有关Scott's Meyers博客的详细信息。
cache
在每次循环迭代结束时被销毁,从而调用其子对象的析构函数。
使用packaged_task
或确保为您的cache
保留一个共享指针副本的容器,以避免等待析构函数。就个人而言,我会选择packeged_task
答案 2 :(得分:0)
正如您所注意到的那样,future
future
std::async
的{{1}} d-tor阻止等待异步操作完成(future
成为ready
{1}})。
在您的情况下,cache
对象在每个循环迭代中超出范围,因此被破坏,并且与它所拥有的future
一起被破坏,因此您可以看到上述效果。