Parallel Pattern Library(PPL)學習筆記

ninja_ken發表於2018-12-31

關於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會在同一個執行緒中執行)

錯誤的寫法包括:

  1. 直接將task1的宣告用try catch保護起來
  2. 直接將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()那一行,保證程式碼會在那裡丟擲異常(而不是其他的執行緒,個人猜測).

相關文章