如何从卡萨布兰卡的多个任务中捕获异常

时间:2016-12-22 16:46:32

标签: c++ exception casablanca ppl cpprest-sdk

我正在尝试使用&& 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能够捕获首先发生的两个异常中的任何一个。我怎么能抓到另一个?

1 个答案:

答案 0 :(得分:1)

您必须为每个子任务添加基于任务的最终延续。 我建议重新抛出你捕获的任何异常,但这可能是一个坏主意,因为延续任务没有意识到2个例外是等价的,见下面的证明示例。
输出:
抓住了 抓到了最后一个 抓住了b

此外,如果您取消睡眠,您将收到一个&#34;跟踪/断点陷阱&#34;异常。

#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();
}