1

我正试图从内部捕捉恐慌par_iter()并继续我在par_iter封锁后所拥有的东西。

如果我有这个,我会正确地得到所有东西并且没有恐慌:

let dog: Dog = Dog {
    name: "Dog",
    vector: vec![1, 2, 3, 4, 5],
};
let cat: Cat = Cat {
    name: "Cat",
    vector: vec![1, 2, 3],
};
let pig: Pig = Pig {
    name: "Pig",
    vector: vec![1, 2, 3, 4, 5],
};
let mut v: Vec<Box<dyn Animal>> = Vec::new();
v.push(Box::new(cat));
v.push(Box::new(dog));
v.push(Box::new(pig));

let total = v
    .par_iter()
    .map(|x| {
        println!("{} vector[1] is {:?}", &x.name(), &x.vector()[1]);
        x.vector()[1].clone()
    })
    .collect::<Vec<(i32)>>();

let sum: i32 = total.iter().sum();
println!("sum: {}", sum);

我得到总和后par_iter

Cat vector[1] is 2
Dog vector[1] is 2
Pig vector[1] is 2
sum: 6

当我尝试访问超过向量长度的索引时,我仍然打印我所拥有的任何内容,包括恐慌,但不要到达sum

let total = v
    .par_iter()
    .map(|x| {
        println!("{} vector[4] is {:?}", &x.name(), &x.vector()[4]);
        x.vector()[4].clone()
    })
    .collect::<Vec<(i32)>>();

let sum: i32 = total.iter().sum();
println!("sum: {}", sum);

结果:

     Running `target/debug/playground`
thread '<unnamed>' panicked at 'index out of bounds: the len is 3 but the index is 4', /rustc/4560ea788cb760f0a34127156c78e2552949f734/src/libcore/slice/mod.rs:2717:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
Standard Output
Dog vector[4] is 5
Pig vector[4] is 5

我试图检查如果我实现了我能做什么panic_handler

let panic_handler = move |err: Box<dyn Any + Send>| {
    println!("hello");
};
rayon::ThreadPoolBuilder::new()
    .num_threads(2)
    .panic_handler(panic_handler)
    .build_global()
    .unwrap();

它不起作用,甚至没有使用:

warning: unused variable: `err`
  --> src/main.rs:52:31
   |
52 |     let panic_handler = move |err: Box<dyn Any + Send>| {
   |                               ^^^ help: consider prefixing with an underscore: `_err`

操场

我真正的问题不是超出向量的范围,而是在par_iter我不知道它是否会恐慌时捕捉恐慌。我的目标是收集结果并继续处理没有恐慌的事情。

4

2 回答 2

1

我的问题在 Rust 用户论坛中得到了回答::std::panic::catch_unwind()

use ::rayon::prelude::*;

trait Animal: Sync + Send {
    fn vector(self: &'_ Self) -> Vec<i32>;
    fn name(self: &'_ Self) -> String;
}

struct Cat {
    name: &'static str,
    vector: Vec<i32>,
}

impl Animal for Cat {
    fn vector(self: &'_ Self) -> Vec<i32> {
        self.vector.clone()
    }

    fn name(self: &'_ Self) -> String {
        self.name.to_string()
    }
}

struct Dog {
    name: &'static str,
    vector: Vec<i32>,
}

impl Animal for Dog {
    fn vector(self: &'_ Self) -> Vec<i32> {
        self.vector.clone()
    }

    fn name(self: &'_ Self) -> String {
        self.name.to_string()
    }
}

struct Pig {
    name: &'static str,
    vector: Vec<i32>,
}

impl Animal for Pig {
    fn vector(self: &'_ Self) -> Vec<i32> {
        self.vector.clone()
    }

    fn name(self: &'_ Self) -> String {
        self.name.to_string()
    }
}

fn main() {
    ::rayon::ThreadPoolBuilder::new()
        .num_threads(2)
        // .panic_handler(move |_: Box<dyn Any + Send>| println!("hello"))
        .build_global()
        .unwrap();

    match ::std::panic::catch_unwind(move || {
        let dog: Dog = Dog {
            name: "Dog",
            vector: vec![1, 2, 3, 4, 5],
        };
        let cat: Cat = Cat {
            name: "Cat",
            vector: vec![1, 2, 3],
        };
        let pig: Pig = Pig {
            name: "Pig",
            vector: vec![1, 2, 3, 4, 5],
        };
        let v: Vec<Box<dyn Animal>> = vec![Box::new(cat), Box::new(dog), Box::new(pig)];
        let total = v
            .par_iter()
            .map(|x| {
                let vector_4 = x.vector()[4].clone();
                println!("{} vector[4] is {:?}", &x.name(), vector_4);
                vector_4
            })
            .collect::<Vec<(i32)>>();
        let sum: i32 = total.iter().sum();
        println!("sum: {}", sum);
    }) {
        Ok(()) => (),
        Err(err) => {
            let err_msg = match (err.downcast_ref(), err.downcast_ref::<String>()) {
                (Some(&s), _) => s,
                (_, Some(s)) => &**s,
                _ => "<No panic message>",
            };
            eprintln!("Rayon panicked: {}", err_msg);
        }
    }
    println!("This code is always reached");
}
于 2019-11-28T17:48:23.843 回答
1

尝试使用getSome(element)如果索引 4 处有元素,则返回,None否则返回):

let total = v.par_iter().map(|x| {
    println!("{} vector[4] is {:?}", &x.name(), &x.vector().get(4));
    x.vector().get(4).map(|x| x.clone())
}).collect::<Vec<Option<i32>>>();

然后,total将包含Some(n)相应元素所在的位置,None否则。

于 2019-11-28T15:44:50.057 回答