推荐使用C++ REST SDK中的并行模式库(PPLX)

虽然std提供了threadasync,但今天遇到了async不能通过匿名的方式使用问题,所以我还是觉得PPLX更方便些。

无论是哪种方式,都是为了简单方便的创建线程。先说说threadasync,有人研究提出,async的抽象级别更高,应优先使用async。我经常用到的一个场景是创建一个匿名线程,而且不需要知道它什么时候结束(因为很确定这个线程不会长久运行)。

例如下面示例,在一个while循环里,每次创建1个匿名线程,匿名线程中输出async并等待2秒后退出线程。

#include <future>
#include <iostream>
using namespace std;

void testTask()
{
	cout << "async" << endl;
	std::this_thread::sleep_for(std::chrono::seconds(2));
}

int main()
{
	int count = 3;

	while (count)
	{
		async([] 
		{
			testTask();
		});

		--count;
	}

	cout << "command end" << endl;

	cin.get();
	return 0;
}

期望输出是:

command end
async
async
async

然而实际输出是

async
等待2秒
async
等待2秒
async
等待2秒
command end

也就是说,每个线程不是并行运行,而是先后运行。查了资料,cppreference解释了这种问题:

若从 std::async 获得的 std::future 未被移动或绑定到引用,则在完整表达式结尾, std::future 的析构函数将阻塞直至异步计算完成,实质上令如下代码同步。

std::async(std::launch::async, []{ f(); }); // 临时量的析构函数等待 f()
std::async(std::launch::async, []{ g(); }); // f() 完成前不开始

说白了,async返回的future变量必须被保存起来,直至线程结束,否则该会编程同步执行。卧槽那就不能愉快的写匿名线程了!

嘛~还好C++ REST SDK提供的并行模式库(PPLX)是可以做到的。如下演示代码,将async改为使用task即可。

#include <iostream>
#include <pplx/pplxtasks.h>
using namespace Concurrency;
using namespace std;
using namespace std::chrono;

void testTask()
{
	cout << "async" << endl;
	std::this_thread::sleep_for(std::chrono::seconds(2));
}

int main()
{
	int count = 3;

	while (count)
	{
		task<void>([] 
		{
			testTask();
		});

		--count;
	}

	cout << "command end" << endl;

	cin.get();
	return 0;
}

留下评论

您的邮箱地址不会被公开。 必填项已用 * 标注