Dom*_*ins 42 c++ asynchronous future promise packaged-task
我应该什么时候使用std::promise过std::async或std::packaged_task?你能告诉我何时使用它们的实际例子吗?
use*_*016 50
std::async得到一个简洁明了的方法std::future,但是:
它并不总是启动一个新线程; 传递std::launch::async作为第一个参数来强制它.
auto f = std::async( std::launch::async, func );
Run Code Online (Sandbox Code Playgroud)该std::~future析构函数可以阻止,直到新线程完成
auto sleep = [](int s) { std::this_thread::sleep_for(std::chrono::seconds(s)); };
{
auto f = std::async( std::launch::async, sleep, 5 );
}
Run Code Online (Sandbox Code Playgroud)
通常我们期望只有.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 );
}
Run Code Online (Sandbox Code Playgroud)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";
Run Code Online (Sandbox Code Playgroud)
在这里我们只运行任务package(1),并在它返回后,f准备就绪,因此没有阻塞.get().
有一个特性std::packaged_task使它对线程非常有用.您可以std::thread使用a 初始化而不仅仅是一个函数,std::packaged_task它提供了一种非常好的方式来获取'std :: future'.考虑以下:
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();
Run Code Online (Sandbox Code Playgroud)
因为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();
Run Code Online (Sandbox Code Playgroud)
新线程将等待我们 .get()
所以,一般来说,回答你的问题:
std::async仅用于简单的事情,比如做一些通话无阻塞,但牢记评论上面阻塞.使用std::packaged_task轻松搞定一个std::future,并运行它作为一个单独的线程
std::thread{ std::move(package), param }.detach();
Run Code Online (Sandbox Code Playgroud)
要么
std::thread t { std::move(package), param };
Run Code Online (Sandbox Code Playgroud)std::promise当您需要对未来进行更多控制时使用.
另请参见std::shared_future并在线程之间传递异常std::promise::set_exception
Kla*_*end -1
Promise 用于存储使用 std::async 等计算得出的值。请参阅http://en.cppreference.com/w/cpp/thread/promise
我可以想象您想知道 std::packaged_task 和 std::async 之间的区别(在最常见的方法中,std::async 现在启动一个单独的线程来运行函数/lambda/等,并进行(可能)昂贵的计算。 std::packaged_task 用于使用参数的当前值包装函数/lambda/等,以便您稍后可以同步或在单独的线程中运行它。
std::packaged_task 和 std::async 都提供了一个 std::future ,一旦运行,它将包含包装函数/lambda/等的结果。在内部, std::future 使用 std::promise 来保存该结果。