当一个操作可以独立异步执行时,可以用 std::async 创建异步任务。异步任务的返回值就是任务函数的返回值,保存在 std::future(期望)中,需要结果时再通过 .get() 获取。注意 get 内部使用了 std::move。
int calculateBill(int base)
{
Sleep(3000);
return base * 2;
}
int main(...)
{
std::future<int> _ans = std::async(calculateBill, 100); //创建异步任务, 任务返回值保存在std::future中
//执行其他任务
cout << "1111" << endl;
cout << "222222" << endl;
Sleep(1);
cout << "3333333" << endl;
cout << "444444" << endl;
//需要异步任务结果的时候, 如果没返回 那么将会等待至返回
cout << _ans.get() << endl;//get操作会阻塞
while (true)
{
Sleep(100);
}
system("pause");
return 0;
}
std::async 提供了 std::thread 所不具备的返回值功能。
异步启动策略
创建异步任务时还可以指定启动策略:
std::launch::async //开一个新线程执行
std::launch::deferred //目标函数的调用延迟到wait或者get函数才执行 等同于 std::launch::sync
std::launch::async | std::launch::deferred //等同于std::launch::any
std::future<int> _ans = std::async( std::launch::async,calculateBill, 100); //异步执行
std::future<int> _ans = std::async( std::launch::deferred,calculateBill, 100);//等到get 或者wait才执行
使用 std::packaged_task 封装任务
还可以用 std::packaged_task 来进一步封装任务,适合处理消息队列等场景。
typedef std::packaged_task<int(int)> task;
int calculateBill(int base)
{
Sleep(500);
return base * 2;
}
int main(...)
{
std::vector<task> tasks;
tasks.push_back(std::move(task(calculateBill)));
tasks.push_back(std::move(task(calculateBill)));
tasks.push_back(std::move(task(calculateBill)));
tasks.push_back(std::move(task(calculateBill)));
tasks.push_back(std::move(task(calculateBill)));
tasks.push_back(std::move(task(calculateBill)));
tasks.push_back(std::move(task(calculateBill)));
tasks.push_back(std::move(task(calculateBill)));
tasks.push_back(std::move(task(calculateBill)));
tasks.push_back(std::move(task(calculateBill)));
int i = 0;
for (auto & task : tasks)
{
task(++i);
std::future<int> ans1 = task.get_future();
cout << ans1.get() << endl;//阻塞会等待结果的返回
}
system("pause");
return 0;
}
并发处理
也可以用多线程并发地执行任务队列:
int i = 0;
for (auto & task : tasks)
{
std::thread t([&]
{
task(++i);
std::future<int> ans1 = task.get_future();
cout << ans1.get() << endl;
});
t.detach();
}