首页 文章

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

提问于
浏览
11

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

我知道你 should not 创建和处理这样的错误 . 这只是为了举个例子 .

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

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 回答

  • 9

    暂且不说“你应该尽可能地使用 Result ," yes, this is basically how you catch a panic in Rust. Keep in mind that " recover”也许不是在Rust中表达这一点的最佳方式 . 你没有真正恢复Rust中的恐慌,你将它们隔离,然后检测它们 . 没有 On Error Resume Next :P .

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

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

    这是一个显示这两者的例子 . 你也可以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);
                }
            }
        }
    }
    

相关问题