Dun*_*gor 15 concurrency scala exception-handling actor
我一直在努力回答是否有一个标准的Scala函数用于运行超时的块?,如果在Future中抛出异常,则会遇到问题.
def runWithTimeout[T](timeoutMs: Long)(f: => T) : Option[T] = {
awaitAll(timeoutMs, future(f)).head.asInstanceOf[Option[T]]
}
Run Code Online (Sandbox Code Playgroud)
以便
runWithTimeout(50) { "result" } should equal (Some("result"))
runWithTimeout(50) { Thread.sleep(100); "result" } should equal (None)
Run Code Online (Sandbox Code Playgroud)
但是如果我在我的块中抛出一个异常它不会泄漏,但是被吞下 - 所以下面的代码失败了"..没有抛出异常"
intercept[Exception] {
runWithTimeout(50) { throw new Exception("deliberate") }
}.getMessage should equal("deliberate")
Run Code Online (Sandbox Code Playgroud)
Syserr有一条带有消息的堆栈跟踪
<function0>: caught java.lang.Exception: deliberate
Run Code Online (Sandbox Code Playgroud)
但我无法找到Scala运行时中打印的位置.
除了在另一个块中包装f以捕获异常并在抛出时传播它们,有没有办法说服awaitAll和/或Future抛出?
Rex*_*err 14
简答:不.
当您在线程上下文中工作时,异常不会执行您想要的操作,因为您希望了解调用者中的异常,并且异常发生在将来的线程中.
相反,如果你想知道异常是什么,你应该返回Either[Exception,WhatYouWant]- 当然,你必须在将来捕获该异常并将其打包.
scala> scala.actors.Futures.future{
try { Right("fail".toInt) } catch { case e: Exception => Left(e) }
}
res0: scala.actors.Future[Product with Serializable with Either[Exception,Int]] = <function0>
scala> res0() // Apply the future
res1: Product with Serializable with Either[Exception,Int] =
Left(java.lang.NumberFormatException: For input string: "fail")
Run Code Online (Sandbox Code Playgroud)
Vik*_*ang 10
免责声明:我为Typesafe工作
或者....你可以使用Akka,它可以给你你想要的东西,而不必为它完成箍.
val f: Future[Int] = actor !!! message
Run Code Online (Sandbox Code Playgroud)
然后
f.get
Run Code Online (Sandbox Code Playgroud)
将抛出actor中发生的异常
f.await.exception
Run Code Online (Sandbox Code Playgroud)
会给你一个选项[Throwable]