举个例子
suspend fun foo() {
try {
suspendCoroutine { cont -> throw Error() }
} catch (ex: Throwable) {
println("catch")
}
println("done")
}
这样throw其实和cont.resumeWithException(Error())
效果一样,会打印”catch”和”done”。
不过如果是这样
suspend fun foo() {
try {
suspendCoroutine { cont ->
thread(name = "thread-0") { throw Error() }
}
} catch (ex: Throwable) {
println("catch")
}
println("done")
}
这样只会打印出thread-0上的Exception信息。
原因很简单,异常是在thread-0上抛出的,而不resume/resumeWithException
的话,这个协程就永远都不会继续执行了
这种情况其实应该用
cont.resumeWithException(Error())
来代替throw。
不过能不能还用throw呢?当然可以,很简单,那就这样
thread(name = "thread-0") {
Thread.currentThread().setUncaughtExceptionHandler { _, ex ->
cont.resumeWithException(ex)
}
throw Error()
}
实际中一般是遇到这样的场景
suspendCoroutine { cont->
threadPool.submit {
try {
val result = blockOperation() // may throw exception
cont.resume(result)
} catch (ex: Throwable) {
cont.resumeWithException(ex)
}
}
}
改造下
fun <T> ExcecutorService.submitWithContinuatioin(cont: Continuation<*>, Callable<T> task) {
this.submit {
Thread.currentThread().setUncaughtExceptionHandler { _, e -> cont.resumeWithException(e) }
task.call()
}
}
suspendCoroutine { cont ->
threadPool.submitWithContinuation(cont) {
cont.resume(blockOperation())
}
}
不用每次都要写try…catch啦