关于PPL是什么,可以搜索关键字MSDN PPL了解详情。这里谈一下困扰自己好一阵子的一个地方--task chain中抛出异常的处理,一来可为其他码农同行参考,二来给自己做个记录,以免日后忘却。
Value-based continuation的成功尝试
void testValueBasedContinuation() { concurrency::task<void> task1([] { throw std::exception("Hello"); }); //set a breakpoint here, and see the wcout IS executed auto task2 = task1.then([]() { std::cout << "continuation" << std::endl; }); try { task2.wait(); } catch (std::exception& e) { std::cout << "exception" << std::endl; } }
这里的要点在于,value-based continuation中continuation task的执行一定是在previous task执行完成之后,因此将continuation task用try catch(T-C)保护起来即可。(个人猜测,value-based chain会在同一个线程中执行)
错误的写法包括:
- 直接将task1的声明用try catch保护起来
- 直接将auto task2一句用try catch保护起来
原因是,声明处并不是task的真正执行的地方,保护起来并没有作用
导致PPL库抛出如下异常
~_ExceptionHolder() { if (_M_exceptionObserved == 0) { // If you are trapped here, it means an exception thrown in task chain didn't get handled. // Please add task-based continuation to handle all exceptions coming from tasks. // this->_M_stackTrace keeps the creation callstack of the task generates this exception. _REPORT_PPLTASK_UNOBSERVED_EXCEPTION(); } }
Task-based continuation的成功尝试
void testTaskBasedContinuation() { concurrency::task<void> task1([] { throw std::exception("Hello"); }); auto task2 = task1.then([](concurrency::task<void>& previous) { previous.get(); std::cout << "continuation" << std::endl; }); try { task2.wait(); } catch (std::exception& e) { std::cout << "exception" << std::endl; } }
这里的关键是previous.get()那一行,保证代码会在那里抛出异常(而不是其他的线程,个人猜测).