问题描述
我一直在努力回答是否有标准的 Scala 函数来运行带有超时的块?, 如果在 Future 中抛出异常,就会遇到问题.
I've been working up my answer to Is there a standard Scala function for running a block with a timeout?, and have run into a problem if an exception is thrown in a Future.
def runWithTimeout[T](timeoutMs: Long)(f: => T) : Option[T] = {
awaitAll(timeoutMs, future(f)).head.asInstanceOf[Option[T]]
}
这样
runWithTimeout(50) { "result" } should equal (Some("result"))
runWithTimeout(50) { Thread.sleep(100); "result" } should equal (None)
但是如果我在我的块中抛出异常,它不会泄漏,而是被吞下 - 因此以下失败并显示..没有抛出异常"
But if I throw an exception in my block it doesn't leak, but is swallowed - so that the following fails with "..no exception was thrown"
intercept[Exception] {
runWithTimeout(50) { throw new Exception("deliberate") }
}.getMessage should equal("deliberate")
Syserr 有一个带有消息的堆栈跟踪
Syserr has a stack trace with the message
<function0>: caught java.lang.Exception: deliberate
但我在 Scala 运行时中找不到打印的位置.
but I can't find where in the Scala runtime that is printed.
除了将 f 包装在另一个块中以捕获异常并在抛出时传播它们,还有什么方法可以说服 awaitAll 和/或 Future 抛出?
Apart from wrapping f in another block which catches exceptions and propagates them if thrown, is there any way to persuade awaitAll and/or Future to throw?
推荐答案
简短回答:否.
当您在线程上下文中工作时,异常不会做您想做的事,因为您想知道调用者中的异常,而异常发生在未来的线程中.
Exceptions don't do what you want when you're working in a threaded context, because you want to know about the exception in the caller, and the exception happens in the future's thread.
相反,如果你想知道异常是什么,你应该返回一个Either[Exception,WhatYouWant]
——当然,你必须在未来捕捉到那个异常并打包.
Instead, if you want to know what the exception was, you should return an Either[Exception,WhatYouWant]
--of course, you have to catch that exception within the future and package it up.
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")
这篇关于我如何掌握 Scala Future 中抛出的异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!