簡単に言えば、タスクの 1 つでスローされた例外がタスク、その継続の 1 つ、またはメイン app によってキャッチされないため、処理されない (観察されない) 例外があります。最初のタスクの get は、2 番目のタスクの task::get への呼び出しが発生する前に、スタックをアンワインドします。
より単純化されたコードはstd::terminate
、タスクでスローされた例外が処理されないために呼び出されることを示しています。のコメントを外すと、例外が再スローさresult.get()
れるため、への呼び出しが妨げられます。std::terminate
task::get
#include <pplx/pplx.h>
#include <pplx/pplxtasks.h>
#include <iostream>
int main(int argc, char* argv[])
{
try
{
auto result = pplx::create_task([] ()-> int
{
throw std::exception("task failed");
});
// actually need wait here till the exception is thrown, e.g.
// result.wait(), but this will re-throw the exception making this a valid use-case
std::cout << &result << std::endl; // use it
//std::cout << result.get() << std::endl;
}
catch (std::exception const& ex)
{
std::cout << ex.what() << std::endl;
}
return 0;
}
の提案を見てくださいpplx::details::_ExceptionHandler::~_ExceptionHolder()
//pplxwin.h
#define _REPORT_PPLTASK_UNOBSERVED_EXCEPTION() do { \
__debugbreak(); \
std::terminate(); \
} while(false)
//pplxtasks.h
pplx::details::_ExceptionHandler::~_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::get
でそのタスクでスローされた例外が発生します。これにより、 への 2 番目の呼び出しが明らかに妨げられるtask::get
ため、2 番目のタスクの例外は処理されません (「監視されない」ままです)。
2 番目のタスクのデストラクタが呼び出され、スタックの巻き戻し中にもう 1 つの例外が再スローされ、'abort' が呼び出されます。
2 番目のタスクのデストラクタは、std::terminate() (std::abort() を呼び出す) を呼び出すだけの例外を再スローしません。
見る。コンカレンシー ランタイムでの例外処理