rust - 在另一个线程中从 `panic!` 恢复

标签 rust

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

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

但是,我想知道从 panic 中恢复过来的最佳方法是什么。这就是我现在拥有的:

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!");
}

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

最佳答案

撇开“你应该尽可能使用 Result”,是的,这基本上就是你在 Rust 中捕捉 panic 的方式。请记住,“恢复”可能不是在 Rust 中表达这一点的最佳方式。在 Rust 中,您并没有真正从 panic 中恢复过来,您隔离它们,然后检测它们。没有 On Error Resume Next :P.

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

第二件事是 nightly 中有一个名为 catch_panic 的新 API,它可以让您隔离 panic , 无需启动线程。也就是说,它具有与生成新线程相同的限制:您不能跨隔离边界传递非 '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);
            }
        }
    }
}

关于rust - 在另一个线程中从 `panic!` 恢复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30824258/

相关文章:

rust - 为什么 VecDeque 的尾部成员指向第一个元素而不是最后一个元素?

types - 如何表示缺失或无效的值?

rust - 将可变上下文传递给回调

rust - 如何为 Clap Args 使用内部库枚举

module - 我可以在不为每个文件引入模块的情况下将 crate 拆分为多个文件吗?

recursion - Rust-在递归函数中收集Vec的切片

rust - 特征类型和生命周期问题

rust - Rust中的二进制文件和库文件有什么区别? [复制]

rust - 使用 STM32f1xx_hal crate 时借用移动值错误

time - 如何在 Rust 中对程序进行基准测试?