在Kotlin协程被取消之后,抛不出异常抛出

使用kotlinx.coroutines lib如果在协程被取消后抛出异常,我不能捕捉到异常。 这导致应用程序崩溃。

fun foo() { val job = launch(UI) { try { Log.d("TAG", "Start coroutine") run(CommonPool) { Log.d("TAG", "Start bg task") // Intentionally make bg task running for a long time SystemClock.sleep(2000) Log.d("TAG", "Throw bg task exception") throw RuntimeException("Bg task exception") } } catch (e: Exception) { Log.e("TAG", "Handle coroutine exception", e) } } launch(UI) { delay(1000) Log.d("TAG", "Cancel job = ${job.cancel()}") } 

}

在Android上运行这个函数会产生下面的日志输出

 07-26 15:09:10.038 31518-31518/co.foo.bar D/MainActivity: Start coroutine 07-26 15:09:10.044 31518-31547/co.foo.bar D/MainActivity: Start bg task 07-26 15:09:11.046 31518-31518/co.foo.bar D/MainActivity: Cancel job = true 07-26 15:09:11.047 31518-31518/co.foo.bar E/MainActivity: Handled coroutine exception java.util.concurrent.CancellationException: Job was cancelled at kotlinx.coroutines.experimental.JobSupport$CompletedExceptionally.getException(Job.kt:921) at kotlinx.coroutines.experimental.RunCompletion.afterCompletion(Builders.kt:198) ... at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 07-26 15:09:12.046 31518-31547/co.foo.bar D/MainActivity: Throwing bg task exception --------- beginning of crash 07-26 15:09:12.046 31518-31547/co.foo.bar E/AndroidRuntime: FATAL EXCEPTION: ForkJoinPool.commonPool-worker-1 Process: co.foo.bar, PID: 31518 java.lang.RuntimeException: Bg task exception at co.foo.barsample.MainActivity$onCreate$1$job$1$1.doResume(MainActivity.kt:36) at kotlin.coroutines.experimental.jvm.internal.CoroutineImpl.resume(CoroutineImpl.kt:54) at kotlinx.coroutines.experimental.DispatchTask.run(CoroutineDispatcher.kt:120) at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1383) at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:256) at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1123) at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1961) at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1909) at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:128) 07-26 15:09:12.050 1705-2190/system_process W/ActivityManager: Force finishing activity co.foo.bar/co.foo.barsample.MainActivity 

似乎是调用cancel()抛出CancellationException被成功捕获。 但是后续的RuntimeException没有被捕获。 我想在作业被取消后的以下异常应该被lib忽略? 或者我可以如何取消作业,而不会抛出CancellationException异常?

使用CoroutineExceptionHandler作为additinoal协程上下文来处理异常,用于launchrun

 run(CommonPool + CoroutineExceptionHandler({ _, e -> Log.e("TAG", "CoroutineExceptionHandler", e) })) { ... } 

要么

 launch(UI + CoroutineExceptionHandler({ _, e -> Log.e("TAG", "CoroutineExceptionHandler", e) })) { ... }