在另一个线程中从“恐慌!”中恢复

时间:2015-06-13 22:40:00

标签: rust

我知道在Rust中没有try / catch,你不能从当前恐慌的线程中抛出滚动保存。

我知道你 不应该 创建和处理这样的错误。这只是为了举例说明。

然而,我想知道从恐慌中恢复的最佳方法是什么。这就是我现在所拥有的:

use std::thread;

fn main() {
    println!("Hello, world!");

    let h = thread::spawn(|| {
        thread::sleep_ms(1000);
        panic!("boom");
    });

    let r = h.join();
    match r {
        Ok(r) => println!("All is well! {:?}", r),
        Err(e) => println!("Got an error! {:?}", e)
    }

    println!("Exiting main!");
}

有没有更好的方法来处理来自其他线程的错误?有没有办法捕捉恐慌的信息?这似乎只告诉我错误属于Any类型。谢谢!

1 个答案:

答案 0 :(得分:10)

放在一边"你应该尽可能使用Result,"是的,这基本上是你如何在Rust中引起恐慌。请记住," recover"也许不是Rust中最好的表达方式。你不能从Rust中的恐慌中恢复,你隔离它们,然后检测它们。没有On Error Resume Next:P。

也就是说,有两件事要添加到你的例子中。首先是如何得到恐慌信息。关键的观察是Any,为了使用,必须显式地向下转换为它包含的确切的具体类型。在这种情况下,由于恐慌消息是&'static str,您需要向下转发。

第二件事是夜间有一个名为catch_panic的新API,它可以让您在没有启动线程的情况下隔离恐慌。也就是说,它产生了与生成新线程相同的限制:您无法在隔离边界上传递非'static引用。请注意,这是不稳定添加;还没有关于稳定性的保证,你需要一个夜间编译器来访问它。

这是一个显示这两者的例子。您还可以run this on the Rust Playpen

#![feature(catch_panic)]

use std::thread;

fn main() {
    println!("Hello, world!");

    let h = thread::spawn(|| {
        thread::sleep_ms(500);
        panic!("boom");
    });

    let r = h.join();
    handle(r);

    let r = thread::catch_panic(|| {
        thread::sleep_ms(500);
        panic!(String::from("boom again!"));
    });

    handle(r);

    println!("Exiting main!");
}

fn handle(r: thread::Result<()>) {
    match r {
        Ok(r) => println!("All is well! {:?}", r),
        Err(e) => {
            if let Some(e) = e.downcast_ref::<&'static str>() {
                println!("Got an error: {}", e);
            } else {
                println!("Got an unknown error: {:?}", e);
            }
        }
    }
}