關於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()那一行,保證程式碼會在那裡丟擲異常(而不是其他的執行緒,個人猜測).