Я хочу поймать исключение, которое генерируется из асин c сопрограмм. Следующий код демонстрирует проблему:
import kotlinx.coroutines.*
fun main() = runBlocking<Unit> {
try {
println(failedConcurrentSum())
} catch (e: ArithmeticException) {
println("Computation failed with ArithmeticException")
}
}
suspend fun failedConcurrentSum() = coroutineScope {
try {
val one = async {
try {
delay(1000L)
42
} finally {
println("First child was cancelled")
}
}
val two = async<Int> {
println("Second child throws an exception")
throw ArithmeticException()
}
one.await() + two.await()
} catch (e: ArithmeticException) {
println("Using a default value...")
0
}
}
Это печатает:
Second child throws an exception
First child was cancelled
Computation failed with ArithmeticException
try-catch
внутри failedConcurrentSum
не обрабатывает исключение, выданное val two
. Я могу убедить себя, что это происходит из-за "структурированного параллелизма".
Однако это не объясняет, почему перенос async
внутри coroutineScope
ловит исключение:
suspend fun failedConcurrentSum() = coroutineScope {
try {
val one = coroutineScope {
async {
try {
delay(1000L)
42
} finally {
println("First child was cancelled")
}
}
}
val two = coroutineScope {
async<Int> {
println("Second child throws an exception")
throw ArithmeticException()
}
}
one.await() + two.await()
} catch (e: ArithmeticException) {
println("Using a default value...")
0
}
}
Это печатает:
First child was cancelled
Second child throws an exception
Using a default value...
0
Почему последний ловит исключение, а первый нет?