在使用 C++11 的线程模型时,我注意到
std::packaged_task<int(int,int)> task([](int a, int b) { return a + b; });
auto f = task.get_future();
task(2,3);
std::cout << f.get() << '\n';
和
auto f = std::async(std::launch::async,
[](int a, int b) { return a + b; }, 2, 3);
std::cout << f.get() << '\n';
似乎做同样的事情。我知道如果我运行 std::async
和 std::launch::deferred
可能会有很大的不同,但是在这种情况下有一个吗?
这两种方法有什么区别,更重要的是,在哪些用例中我应该使用其中一种方法?
原文由 nikolas 发布,翻译遵循 CC BY-SA 4.0 许可协议
实际上,如果您使用相当长的函数,您刚刚给出的示例显示了差异,例如
打包任务
A
packaged_task
不会自行启动,您必须调用它:std::async
另一方面,
std::async
和launch::async
将尝试在不同的线程中运行任务:退税
但在你尝试使用
async
之前,请记住返回的未来有一个特殊的共享状态,它要求future::~future
块:因此,如果您想要真正的异步,则需要保留返回的
future
,或者如果情况发生变化您不关心结果:For more information on this, see Herb Sutter’s article
async
and~future
, which describes the problem, and Scott Meyer’sstd::futures
fromstd::async
aren ’t special ,它描述了洞察力。另请注意,此行为 是在 C++14 及更高版本中指定的,但也通常在 C++11 中实现。进一步的差异
通过使用
std::async
您不能再在特定线程上运行您的任务,其中std::packaged_task
可以移动到其他线程。此外,在调用
packaged_task
之前需要调用f.get()
,否则您的程序将冻结,因为未来永远不会准备好:TL;博士
使用
std::async
如果您想要完成某些事情并且并不真正关心它们何时完成,使用std::packaged_task
如果您想结束事情以便将它们移动到其他线程或稍后打电话给他们。或者,引用 Christian 的话: