【发布时间】:2020-12-29 18:39:15
【问题描述】:
我知道了为什么从std::async返回的future有一些特殊的共享状态,wait on returned future通过它在未来的析构函数中发生。但是当我们使用std::pakaged_task 时,它的未来不会表现出相同的行为。
要完成打包任务,您必须从 packaged_task 显式调用 future 对象上的 get()。
现在我的问题是:
- 未来的内部实现可能是什么(思考
std::async与std::packaged_task)? - 为什么相同的行为不适用于从
std::packaged_task返回的future?或者,换句话说,如何停止std::packaged_taskfuture的相同行为?
要查看上下文,请查看以下代码:
它不会等待完成countdown 任务。但是,如果我取消注释 // int value = ret.get();,它将完成 countdown 并且很明显,因为我们实际上是在阻止返回的未来。
// packaged_task example
#include <iostream> // std::cout
#include <future> // std::packaged_task, std::future
#include <chrono> // std::chrono::seconds
#include <thread> // std::thread, std::this_thread::sleep_for
// count down taking a second for each value:
int countdown (int from, int to) {
for (int i=from; i!=to; --i) {
std::cout << i << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::cout << "Lift off!" <<std::endl;
return from-to;
}
int main ()
{
std::cout << "Start " << std::endl;
std::packaged_task<int(int,int)> tsk (countdown); // set up packaged_task
std::future<int> ret = tsk.get_future(); // get future
std::thread th (std::move(tsk),10,0); // spawn thread to count down from 10 to 0
// int value = ret.get(); // wait for the task to finish and get result
std::cout << "The countdown lasted for " << std::endl;//<< value << " seconds.\n";
th.detach();
return 0;
}
如果我使用std::async 在另一个线程上执行任务countdown,无论我对返回的future 对象使用get() 还是不,它都会完成任务。
// packaged_task example
#include <iostream> // std::cout
#include <future> // std::packaged_task, std::future
#include <chrono> // std::chrono::seconds
#include <thread> // std::thread, std::this_thread::sleep_for
// count down taking a second for each value:
int countdown (int from, int to) {
for (int i=from; i!=to; --i) {
std::cout << i << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::cout << "Lift off!" <<std::endl;
return from-to;
}
int main ()
{
std::cout << "Start " << std::endl;
std::packaged_task<int(int,int)> tsk (countdown); // set up packaged_task
std::future<int> ret = tsk.get_future(); // get future
auto fut = std::async(std::move(tsk), 10, 0);
// int value = fut.get(); // wait for the task to finish and get result
std::cout << "The countdown lasted for " << std::endl;//<< value << " seconds.\n";
return 0;
}
【问题讨论】:
-
在第一个程序中,您没有等待线程运行,主线程甚至在该线程启动之前就退出了。
-
@Ayub 在第二个节目中,我也不等了。但是程序本身在未来的析构函数中等待。这就是我关于未来行为差异的问题(来自程序 1 和程序 2)
-
您可以尝试在 std::async 中使用 std::launch::async(或 ...::deferred)。
async析构函数将等待它的未来完成只有如果它已经启动。 -
@olepinto 您的观察似乎是正确的,但它没有回答我的问题。
标签: c++ c++14 stdasync packaged-task std-future