虽然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; }