0

根据MSDN

基于任务的延续总是安排在前面的任务完成时执行,即使前面的任务被取消或抛出异常也是如此。

我不明白这一点,因为我尝试了以下代码,并且当第一个任务通过抛出异常完成时不会调用后续任务。我理解为什么它必须将呼叫转发到被呼叫的站点,concurrency::task::wait但我不明白 MSDN 上的声明是什么意思。我有什么误解?

#include <iostream>

#include <ppl.h>
#include <ppltasks.h>

int main(int argc, char* argv[])
{
    using namespace std;

    concurrency::task<void> task;
    auto task_ticket = concurrency::create_task([]()
    {
        // A continuation task executed asynchronously
        // after the previous task has completed. This
        // is executed even if the previous task fails
        // by being cancelled or throwing an exception.
        throw std::runtime_error("Hello");
    })

        .then([]()
    {
        // This should be executed even though the
        // previous task failed.
        cout << "Task (2) executed" << endl;
    });

    try
    {
        task_ticket.wait();
    }
    catch (std::exception const& e)
    {
        cout << "Exception caught\n";
    }
    return EXIT_SUCCESS;
}
4

1 回答 1

2

您误解了基于价值的延续与基于任务的延续。

给定一个返回类型为 T 的任务对象,您可以为其后续任务提供一个类型为 T 或任务的值。采用 T 类型的延续称为基于值的延续。

您对 create_task 的初始调用返回task<void>。您传递给的 lambda.then接受void作为输入(因为.then([]()等效于.then([](void)),因此延续是基于值的,如果前面的任务抛出,则不会运行。

要声明基于任务的延续,请使用:

auto task_ticket = concurrency::create_task([]()
{
    throw std::runtime_error("Hello");
})
.then([](task<void> antecedent_task)
{
    cout << "Task (2) executed" << endl;
    antecedent_task.get(); // re-throws std::runtime_error
});
于 2017-07-23T01:26:38.370 回答