我应该何时std::promise
使用std::async
或std::packaged_task
?
你能告诉我何时使用它们的实际例子吗?
答案 0 :(得分:43)
std::async
是获得std::future
的简洁方法,但是:
并不总是会启动新线程;将std::launch::async
作为第一个参数来强制它。
auto f = std::async( std::launch::async, func );
std::~future
析构函数可以阻止,直到新线程完成
auto sleep = [](int s) { std::this_thread::sleep_for(std::chrono::seconds(s)); };
{
auto f = std::async( std::launch::async, sleep, 5 );
}
通常我们希望只有.get()
或.wait()
块,但对于从std::future
返回的std::async
,析构函数也可能会阻塞,所以请注意不要阻止主线只是忘了它。
如果std::future
存储在临时生活对象中,std::async
调用将立即停止,因此如果您有以下数据块 10秒删除auto f =
初始化:
auto sleep = [](int s) { std::this_thread::sleep_for(std::chrono::seconds(s)); };
{
auto f1 = std::async( std::launch::async, sleep, 5 );
auto f2 = std::async( std::launch::async, sleep, 5 );
}
std::packaged_task
本身与线程无关:它只是一个仿函数和一个相关的std::future
。请考虑以下事项:
auto task = [](int i) { std::this_thread::sleep_for(std::chrono::seconds(5)); return i+100; };
std::packaged_task< int(int) > package{ task };
std::future<int> f = package.get_future();
package(1);
std::cout << f.get() << "\n";
此处我们只是按package(1)
运行任务,在它返回后,f
已就绪,因此.get()
上没有阻止。
std::packaged_task
的一个特性使它对线程非常有用。您可以使用std::thread
初始化std::packaged_task
,而不仅仅是一个函数,它提供了一种非常好的方式来访问&#39; std :: future&#39;。请考虑以下事项:
std::packaged_task< int(int) > package{ task };
std::future<int> f = package.get_future();
std::thread t { std::move(package), 5 };
std::cout << f.get() << "\n"; //block here until t finishes
t.join();
由于std::packaged_task
不可复制,因此您必须将其移至std::move
的新主题。
std::promise
是一种强大的机制。例如,您可以将值传递给新线程,而无需任何其他同步。
auto task = [](std::future<int> i) {
std::cout << i.get() << std::flush;
};
std::promise<int> p;
std::thread t{ task, p.get_future() };
std::this_thread::sleep_for(std::chrono::seconds(5));
p.set_value(5);
t.join();
新主题会在.get()
所以,一般来说,回答你的问题:
std::async
用于简单的事情,例如打一些非阻塞的电话,但要记住上面阻止的评论。使用std::packaged_task
轻松访问std::future
,并将其作为单独的帖子运行
std::thread{ std::move(package), param }.detach();
或
std::thread t { std::move(package), param };
当您需要对未来进行更多控制时,请使用std::promise
。
答案 1 :(得分:-1)
承诺用于存储使用例如计算的值。一个std :: async。 见http://en.cppreference.com/w/cpp/thread/promise
我可以想象你想知道std :: packaged_task和std :: async之间的区别(在最常见的方法中,std :: async启动一个单独的线程来运行函数/ lambda / etc,可能)计算。 std :: packaged_task用于使用参数的当前值包装函数/ lambda / etc,以便您可以同步或在单独的线程中运行它。
std :: packaged_task和std :: async都提供了一个std :: future,它将在运行后包含包装函数/ lambda / etc的RESULT。 在内部,std :: future使用std :: promise来保存该结果。