虽然std提供了thread和async,但今天遇到了async不能通过匿名的方式使用问题,所以我还是觉得PPLX更方便些。
无论是哪种方式,都是为了简单方便的创建线程。先说说thread和async,有人研究提出,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;
}
