std::async 函数 运行 连续
std::async function running serially
当在 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编译的
这是 C++11 定义的 std::async
的错误特征。它的期货析构函数是特殊的,等待操作完成。有关 Scott's Meyers 博客的更多详细信息。
cache
在每次循环迭代结束时被销毁,从而调用其子对象的析构函数。
使用 packaged_task
或确保您保留指向 cache
的共享指针副本的容器,以避免等待析构函数。就个人而言,我会选择 packeged_task
正如您自己注意到的,std::async
返回的 future
的 future
d-tor 阻塞并等待异步操作完成(对于 future
变成 ready
)。
在您的情况下, cache
对象在每次循环迭代时都超出范围,因此与它所持有的 future
一起被破坏,因此您会看到上述效果。
析构函数中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
存储在一个单独的永久性 future
中,该 future
在 for 循环之外声明。
当在 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编译的
这是 C++11 定义的 std::async
的错误特征。它的期货析构函数是特殊的,等待操作完成。有关 Scott's Meyers 博客的更多详细信息。
cache
在每次循环迭代结束时被销毁,从而调用其子对象的析构函数。
使用 packaged_task
或确保您保留指向 cache
的共享指针副本的容器,以避免等待析构函数。就个人而言,我会选择 packeged_task
正如您自己注意到的,std::async
返回的 future
的 future
d-tor 阻塞并等待异步操作完成(对于 future
变成 ready
)。
在您的情况下, cache
对象在每次循环迭代时都超出范围,因此与它所持有的 future
一起被破坏,因此您会看到上述效果。
析构函数中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
存储在一个单独的永久性 future
中,该 future
在 for 循环之外声明。