Taskflow:异常处理(Exception Handling)

从运行的Taskflow中捕捉异常

当Task抛出异常时,执行器将以tf::Future句柄引用的共享状态存储该异常。

#include <taskflow/taskflow.hpp>
void print_str(char const* str) {
    std::cout << str << std::endl;
}
int main() {
    tf::Executor executor;
    tf::Taskflow taskflow;

    // task抛出一个异常
    taskflow.emplace([](){ throw std::runtime_error("exception"); });

    // Task抛出的异常将会存入future中
    tf::Future<void> future = executor.run(taskflow); 
    try {
        future.get(); // 并在get() 获取
    }
    catch(const std::runtime_error& e) {
        std::cerr << e.what() << std::endl;
    }

    // 上面逻辑的简化版
    // try {
    //     executor.run(taskflow).get();
    // }
    // catch(const std::runtime_error& e) {
    //     std::cerr << e.what() << std::endl;
    // }
}

由于tf::Future是从std::future派生的,它继承了C++标准定义的所有异常处理行为。

异常将会自动取消Taskflow的执行。所有依赖该异常Task的后续任务将无法运行。

#include <taskflow/taskflow.hpp>
void print_str(char const* str) {
    std::cout << str << std::endl;
}
int main() {
    tf::Executor executor;
    tf::Taskflow taskflow;

    tf::Task A = taskflow.emplace([](){ throw std::runtime_error("exception on A"); });
    tf::Task B = taskflow.emplace([](){ std::cout << "Task B\n"; });
    A.precede(B);

    try {
    executor.run(taskflow).get();
    }
    catch(const std::runtime_error& e) {
    std::cerr << e.what() << std::endl;
    }
}

当A抛出异常时,执行者将取消任务流的执行,停止在A之后运行的每个任务。在这种情况下,B不会运行。

当并发任务中,多个Task抛出异常,Taskflow只会存储一个异常,并忽略其他异常:

#include <taskflow/taskflow.hpp>
int main() {
    tf::Executor executor;
    tf::Taskflow taskflow;

    auto [A, B, C, D] = taskflow.emplace(
    []() { std::cout << "TaskA\n"; },
    []() { 
        std::cout << "TaskB\n";
        throw std::runtime_error("Exception on Task B");
    },
    []() { 
        std::cout << "TaskC\n"; 
        throw std::runtime_error("Exception on Task C");
    },
    []() { std::cout << "TaskD will not be printed due to exception\n"; }
    );

    A.precede(B, C);  // A runs before B and C
    D.succeed(B, C);  // D runs after  B and C

    try {
    executor.run(taskflow).get();
    }
    catch(const std::runtime_error& e) {
    // catched either B's or C's exception
    std::cout << e.what() << std::endl;
    }
}

同样,异步Task也依靠future传播异常:

tf::Executor executor;
auto fu = executor.async([](){ throw std::runtime_error("exception"); });
try {
  fu.get();
}
catch(const std::runtime_error& e) {
  std::cerr << e.what() << std::endl;
}

tf::Executor::silent_async 不会返回future,所以其异常会被传播到其父Task,或者忽略(没有父Task时):

tf::Taskflow taskflow;
tf::Executor executor;

// execption will be silently ignored
executor.silent_async([](){ throw std::runtime_error("exception"); });

// exception will be propagated to the parent tf::Runtime task and then its Taskflow
taskflow.emplace([&](tf::Runtime& rt){
  rt.silent_async([](){ throw std::runtime_error("exception"); });
});
try {
  taskflow.get();
}
catch(const std::runtime_error& re) {
  std::cout << re.what() << std::endl;
}

对于tf::Executor::corun 或者 tf::Runtime::corun,会直接抛出异常,如果tf::Runtime::corun没有捕获异常,它将被传播到其父task。

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值