Как ловить исключения из нескольких задач в Касабланке

Я пытаюсь объединить две задачи pplx, используя && оператор задачи, где обе подзадачи могут генерировать исключения.

Я понимаю из документация по госзакупкам что я могу поймать исключение в окончательном продолжении на основе задач. Это работает и в Касабланке.
Тем не менее, я могу поймать только одно исключение в моем последнем продолжении. Если обе подзадачи выбрасываются, одно остается необработанным.

Вот минимальный пример, иллюстрирующий мою проблему:

#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 может перехватить любое из двух исключений, которое произойдет первым. Как я могу поймать другого?

2

Решение

Вам нужно будет добавить окончательное продолжение на основе задач к каждой подзадаче.
Я бы предложил перебросить любое пойманное вами исключение, однако, это, вероятно, было бы плохой идеей, поскольку задача продолжения не осознает, что 2 исключения эквивалентны, см. Пример ниже для доказательства.
Выход:
поймал
поймал финал
поймал б

Кроме того, если вы удалите режим сна, вы получите исключение «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();
}
1

Другие решения

Других решений пока нет …