在另一个线程中从“恐慌!"中恢复 [英] Recovering from `panic!` in another thread

查看:45
本文介绍了在另一个线程中从“恐慌!"中恢复的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道在 Rust 中没有 try/catch,并且您不能从当前处于恐慌状态的线程中抛出滚动保存.

I know that in Rust there is no try/catch, and you can't throw a rolling save from the thread that is currently panicking.

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

I know you should not create and handle errors like this. This is just for example's sake.

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

However, I am wondering what the best way to recover from a panic is. This is what I have now:

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.谢谢!

Is there a better way to handle errors from other threads? Is there a way to capture the message of the panic? This seems to only tell me that the error is of type Any. Thanks!

推荐答案

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

Putting aside "you should be using Result where possible," yes, this is basically how you catch a panic in Rust. Keep in mind that "recover" is perhaps not the best way of phrasing this in Rust. You don't really recover from panics in Rust, you isolate them, then detect them. There is no On Error Resume Next :P.

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

That said, there are two things to add to your example. First is how to get at the panic message. The key observation is that Any, in order to be used, must be explicitly downcast to the exact, concrete type it contains. In this case, since the panic message is a &'static str, you need to downcast to that.

第二件事是 nightly 中有一个名为 catch_panic 的新 API,它可以让您隔离恐慌而不必启动线程.也就是说,它具有与生成新线程相同的限制:您不能跨隔离边界传递非'static 引用.请注意,这是一个不稳定添加;目前还不能保证稳定性,你需要一个夜间编译器来访问它.

The second thing is that there is a new API in nightly called catch_panic that lets you isolate a panic without having to start a thread. That said, it comes with the same restrictions as spawning a new thread: you cannot pass a non-'static reference across the isolation boundary. Note that this is an unstable addition; there are no guarantees about stability yet, and you'll need a nightly compiler to access it.

这是一个示例,显示了这两种情况.您也可以在 Rust Playpen 上运行它.

Here is an example which shows both of those. You can also 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);
            }
        }
    }
}

这篇关于在另一个线程中从“恐慌!"中恢复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆