2015-06-13 28 views
10

我知道,在鏽沒有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。謝謝!

回答

8

暫且不論「你應該用Result如果可能的話,」是的,這基本上是你如何趕在鏽恐慌。請記住,「恢復」可能不是在Rust中對此進行表述的最佳方式。你真的沒有從Rust中的恐慌中恢復過來,你分離出他們,然後檢測到他們。沒有On Error Resume Next:P。

這就是說,有兩件事要添加到你的例子。首先是如何獲得恐慌信息。關鍵的觀察結果是Any爲了被使用,必須明確地向下傾倒到它包含的確切的具體類型。在這種情況下,由於恐慌消息是&'static str,因此您需要向下轉發。

第二件事是,在夜間有一個新的API叫做catch_panic,它可以讓你隔離恐慌而不需要必須啓動一個線程。也就是說,它具有與產生新線程相同的限制:您不能在整個隔離邊界上傳遞非參考參考。請注意,這是一個不穩定的另外;目前還沒有關於穩定性的保證,您需要每晚編譯器才能訪問它。

下面是一個顯示這兩個的例子。你也可以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); 
      } 
     } 
    } 
} 
+0

完美!關於錯誤格式的位是'&'static str'就是我所需要的。謝謝!我有點驚訝,現在Rust已經不穩定了,現在Rust已經不穩定了,但也很高興在他們準備好之前讓他們不在野外。 – jocull

+3

@jocull「1.0」並不意味着「我們完成了」,它只是意味着「好吧,我們現在每隔幾天就會停止打破一切。」如果你期望標準庫是「功能完備」的,因爲Rust的值爲1.0,那麼你將會非常失望。 :) –

+3

@DK .:我寧願說:「如果你期望Rust現在停止發展,它現在是1.0,你會感到驚喜的:)」 –