std::异步函数串行运行

std::async function running serially

本文关键字:运行 函数 异步 std      更新时间:2023-10-16

当在 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来编译它。

>析构函数中的async块返回的std::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);
 }  // <-- When we get here

cache被销毁,这反过来又调用等待线程完成的future析构函数。

您需要做的是从async返回的每个future存储在 for 循环外部声明的单独持久future中。

这是

C++11定义的std::async的错误特征。其期货的破坏者很特殊,等待操作完成。更多詳情請參閱Scott's Meyers博客。

cache在每个循环迭代结束时被销毁,从而调用其子对象的析构函数。

使用 packaged_task 或确保保留指向cache的共享指针副本的容器,以避免等待析构函数。就个人而言,我会选择packeged_task

正如您自己注意到的那样,futurefuture d-tor 返回 std::async 块并等待异步操作完成(让future变得ready(。在您的情况下,cache对象在每次循环迭代中都超出了范围,因此与它所持有的future一起被破坏,因此您会看到上述效果。