如何在 Casablanca 中捕获多个任务的异常
How to catch exceptions from multiple tasks in Casablanca
我正在尝试使用任务的 && operator 加入两个 pplx 任务,其中两个子任务都可以抛出异常。
我从 ppl documentation 了解到我可以在基于任务的最终延续中捕获异常。这在卡萨布兰卡也适用。
但是,在最后的延续中我只能捕捉到一个异常。如果两个子任务都抛出,则有一个未处理。
这是一个说明我的问题的小例子:
#include <pplx/pplxtasks.h>
#include <iostream>
int main(int argc, char *argv[])
{
int a = 0; int b = 0;
auto t1 = pplx::create_task([a] { return a+1; })
.then([](int a) { throw std::runtime_error("a");
return a+1; });
auto t2 = pplx::create_task([b] { return b+1; })
.then([](int b) { throw std::runtime_error("b");
return b+1; });
(t1 && t2)
.then([] (std::vector<int>) { /*...*/ })
.then([] (pplx::task<void> prev) {
try {
prev.get();
} catch (std::runtime_error e) {
std::cout << "caught " << e.what() << std::endl;
}
});
std::cin.get();
}
try/catch 能够捕获两个异常中先发生的那个。我怎样才能抓住另一个?
您必须为每个 sub-task 添加最后的 task-based 延续。
我会建议 re-throwing 您捕获的任何异常,但是,这可能不是一个好主意,因为继续任务没有意识到这 2 个异常是等效的,请参见下面的示例以获取证明。
输出:
抓住了一个
抓住最后一个
抓住了 b
此外,如果您删除睡眠,您将收到 "Trace/breakpoint trap" 异常。
#include <pplx/pplxtasks.h>
#include <iostream>
int main(int argc, char *argv[])
{
int a = 0; int b = 2;
auto t1 = pplx::create_task([a] { return a+1; })
.then([](int a) { throw std::runtime_error("a"); return a+1; })
.then([] (pplx::task<int> prev)
{
int retVal = -1;
try
{
retVal = prev.get();
}
catch (std::runtime_error e)
{
std::cout << "caught " << e.what() << std::endl;
throw e;
}
return retVal;
});
auto t2 = pplx::create_task([b] { return b+1; })
.then([](int b) { throw std::runtime_error("b"); return b+1; })
.then([] (pplx::task<int> prev)
{
int retVal = -1;
try
{
sleep(1);
retVal = prev.get();
}
catch (std::runtime_error e)
{
std::cout << "caught " << e.what() << std::endl;
throw e;
}
return retVal;
});
(t1 && t2)
.then([] (std::vector<int> v) { for(int i : v) { std::cout << i << std::endl; } })
.then([] (pplx::task<void> prev)
{
try
{
prev.get();
}
catch (std::runtime_error e)
{
std::cout << "caught final " << e.what() << std::endl;
}
}).get();
}
我正在尝试使用任务的 && operator 加入两个 pplx 任务,其中两个子任务都可以抛出异常。
我从 ppl documentation 了解到我可以在基于任务的最终延续中捕获异常。这在卡萨布兰卡也适用。 但是,在最后的延续中我只能捕捉到一个异常。如果两个子任务都抛出,则有一个未处理。
这是一个说明我的问题的小例子:
#include <pplx/pplxtasks.h>
#include <iostream>
int main(int argc, char *argv[])
{
int a = 0; int b = 0;
auto t1 = pplx::create_task([a] { return a+1; })
.then([](int a) { throw std::runtime_error("a");
return a+1; });
auto t2 = pplx::create_task([b] { return b+1; })
.then([](int b) { throw std::runtime_error("b");
return b+1; });
(t1 && t2)
.then([] (std::vector<int>) { /*...*/ })
.then([] (pplx::task<void> prev) {
try {
prev.get();
} catch (std::runtime_error e) {
std::cout << "caught " << e.what() << std::endl;
}
});
std::cin.get();
}
try/catch 能够捕获两个异常中先发生的那个。我怎样才能抓住另一个?
您必须为每个 sub-task 添加最后的 task-based 延续。
我会建议 re-throwing 您捕获的任何异常,但是,这可能不是一个好主意,因为继续任务没有意识到这 2 个异常是等效的,请参见下面的示例以获取证明。
输出:
抓住了一个
抓住最后一个
抓住了 b
此外,如果您删除睡眠,您将收到 "Trace/breakpoint trap" 异常。
#include <pplx/pplxtasks.h>
#include <iostream>
int main(int argc, char *argv[])
{
int a = 0; int b = 2;
auto t1 = pplx::create_task([a] { return a+1; })
.then([](int a) { throw std::runtime_error("a"); return a+1; })
.then([] (pplx::task<int> prev)
{
int retVal = -1;
try
{
retVal = prev.get();
}
catch (std::runtime_error e)
{
std::cout << "caught " << e.what() << std::endl;
throw e;
}
return retVal;
});
auto t2 = pplx::create_task([b] { return b+1; })
.then([](int b) { throw std::runtime_error("b"); return b+1; })
.then([] (pplx::task<int> prev)
{
int retVal = -1;
try
{
sleep(1);
retVal = prev.get();
}
catch (std::runtime_error e)
{
std::cout << "caught " << e.what() << std::endl;
throw e;
}
return retVal;
});
(t1 && t2)
.then([] (std::vector<int> v) { for(int i : v) { std::cout << i << std::endl; } })
.then([] (pplx::task<void> prev)
{
try
{
prev.get();
}
catch (std::runtime_error e)
{
std::cout << "caught final " << e.what() << std::endl;
}
}).get();
}