1. std::packaged_task<>
类模板
std::packaged_task
包装任何可调用 (Callable) 目标(函数、 lambda 表达式、 bind 表达式或其他函数对象),使得能异步调用它。其返回值或所抛异常被存储于能通过 std::future 对象访问的共享状态中。
正如 std::function , std::packaged_task 是多态、具分配器的容器:可在堆上或以提供的分配器分配存储的可调用对象。
std::packaged_task
本身和线程没啥关系,它只是一个关联了std::future
的仿函数
2. 代码示例
#include <iostream>
#include <cmath>
#include <thread>
#include <future>
#include <functional>
int f(int x, int y) { return std::pow(x, y); }
// lambda表达式
void task_lambda()
{
std::packaged_task<int(int, int)> task([](int a, int b) {
return std::pow(a, b);
});
std::future<int> result = task.get_future();
// 这里开始执行任务,会阻塞在这里等待lambda表达式里的内容执行完
task(2, 9);
std::cout << "task_lambda:\t" << result.get() << '\n';
}
// bind表达式
void task_bind()
{
std::packaged_task<int()> task(std::bind(f, 2, 11));
std::future<int> result = task.get_future();
// 这里开始执行任务,会阻塞在这里等待f函数里的内容执行完
task();
std::cout << "task_bind:\t" << result.get() << '\n';
}
// 在线程中执行任务
void task_thread()
{
std::packaged_task<int(int, int)> task(f);
std::future<int> result = task.get_future();
// 开启线程,注意 std::packaged_task<>不可复制,因此一定要通过std::move()把任务传入线程
std::thread task_td(std::move(task), 2, 10);
task_td.join();
// 等待线程里的f函数执行完成,返回结果
std::cout << "task_thread:\t" << result.get() << '\n';
}
// async的例子,aync与packaged_task的区别
void test_async()
{
// 这里使用std::launch::async,立即开启异步执行f函数
std::future<int> answer = std::async(std::launch::async, f, 2, 12);
// 在这里等待f函数里的内容执行完
std::cout << "test_async:\t" << answer.get() << '\n';
}
int main()
{
task_lambda();
task_bind();
task_thread();
test_async();
}
3. 参考
https://zh.cppreference.com/w/cpp/thread/packaged_task
https://www.jb51.net/article/179426.htm
https://blog.csdn.net/weiwei9363/article/details/106418146