在suspendCoroutine中用throw代替resumeWithException

举个例子

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  ExcecutorService.submitWithContinuatioin(cont: Continuation<*>, Callable task) {
    this.submit {
        Thread.currentThread().setUncaughtExceptionHandler { _, e -> cont.resumeWithException(e) }
        task.call()
    }
}

suspendCoroutine { cont ->
    threadPool.submitWithContinuation(cont) {
        cont.resume(blockOperation())
    }
}

不用每次都要写try…catch啦

你可能感兴趣的:(Kotlin)