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

joc*_*ull 14 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!");
}
Run Code Online (Sandbox Code Playgroud)

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

DK.*_*DK. 11

暂且不说"你应该尽可能使用Result",是的,这基本上就是你在Rust中引起恐慌的原因.请记住,"恢复"可能不是在Rust中表达这一点的最佳方式.你没有真正从Rust中的恐慌恢复,你它们隔离,然后检测它们.没有On Error Resume Next:P.

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

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

这是一个显示这两者的例子.您也可以在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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @jocull"1.0"并不意味着"我们已经完成",它只是意味着"好吧,我们现在每隔几天就会停止破坏一切." 如果你希望标准库是"功能完整",因为Rust是1.0,那你将会非常失望.:) (4认同)
  • @DK.:我宁愿说"如果你希望Rust现在停止进化,那它就是1.0,那你就会惊喜万分":) (3认同)