2017-05-07 6 views
1

Tryは、以下の例のようにスレッド間例外をキャッチすると考えていました。私はそうではないと思います:子スレッドで発生した例外をどうやってキャッチしますか?Scala:子スレッドで例外をキャッチする方法

// Simple class that throws error 
class Child extends Runnable { 
    def run { 
    val exception: Exception = new Exception("Foo") 
    val i = 1 
    Thread.sleep(1000) 
    val lines = scala.io.Source.fromFile("/tmp/filefoobar.txt").mkString 
    Thread.sleep(1000) 
    } 
} 
// spawn the class above 
def Parent() = { 
    val doit = Try { 
    val t = new Thread(new Child) 
    t.start 
    t.join() 
    } 

    doit match { 
    case Success(v) => println("uh oh did not capture error") 
    case Failure(v) => println("good we caught the error") 
    } 
} 

出力 スカーラ>親()

Exception in thread "Thread-35" java.io.FileNotFoundException: /tmp/filefoobar.txt (No such file or directory) 
    at java.io.FileInputStream.open0(Native Method) 
    at java.io.FileInputStream.open(FileInputStream.java:195) 
    at java.io.FileInputStream.<init>(FileInputStream.java:138) 
    at scala.io.Source$.fromFile(Source.scala:91) 
    at scala.io.Source$.fromFile(Source.scala:76) 
    at scala.io.Source$.fromFile(Source.scala:54) 
    at $line120.$read$$iw$$iw$Child.run(<console>:16) 
    at java.lang.Thread.run(Thread.java:745) 
uh oh did not capture error 

答えて

3

は、非同期タスクの結果を処理するために先物を使って考えてみましょうあなたが書き換えた場合と言っ.Are

import ExecutionContext.Implicits.global 
val resultFuture: Future[Unit] = Future { new Child.run } 
resultFuture.onComplete (result: Try[Unit] => ...) 
0

子は、ファイルにアクセスするとJREをキャプチャし、デフォルトの動作を以下の例外を発生させます。スタックトレースを印刷し、親プロセスに例外を伝播します。親プロセスは、出力で見られるようにParentを取得します。

あなたができることは、子プロセスで例外をキャッチし、親がそれを処理できるように例外をスローすることです。

+0

私はエラーをキャッチした場合、子がtryブロックとして例外をスローすると、親はその例外を取得しますか?例外を「自分自身」に投げ込むにはどうすればよいですか?結局のところ、コードの中には、エラーがスローされてスタックに上がり、親に到達しません。子供に明示的にエラーを投げることはできますか? – user7938511

0

あなたは例外を設定し、試してからそれを再スローするThread.setUncaughtExceptionHandlerを使用することができます。

import java.lang.Thread.UncaughtExceptionHandler 

def Parent() = { 

    @volatile 
    var maybeException: Option[Throwable] = None 

    val doit = Try { 
    val target = new Child 
    val t = new Thread(target) 
    t.setUncaughtExceptionHandler(new UncaughtExceptionHandler { 
     override def uncaughtException(t: Thread, th: Throwable): Unit = { 
     maybeException = Some(th) 
     } 
    }) 
    t.start() 
    t.join() 

    maybeException.foreach(th => throw th) 
    } 

    doit match { 
    case Success(v) => println("uh oh did not capture error") 
    case Failure(v) => println("good we caught the error") 
    } 
} 
+0

上記のコードはあまりコンパイルされません。 :34:エラー:タイプの不一致。 が見つかりました:(スレッド、のThrowable)=>単位 必要:java.lang.Thread.UncaughtExceptionHandler t.setUncaughtExceptionHandler((T:スレッド、E:のThrowable)=> { ^ – user7938511

+0

は申し訳ありません怠けているではない、私がしようでした – user7938511

+0

Scala 2.11を使用しているようですが、私の例は2.12用ですので、2.11で動作するように更新しました。 –