当一个操作可以独立异步执行时,可以用 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();
	}

参考:https://github.com/progschj/ThreadPool