gpt4 book ai didi

exception - Kotlin 协程无法处理异常

转载 作者:行者123 更新时间:2023-12-04 08:20:18 24 4
gpt4 key购买 nike

我在玩协程,发现了一些非常奇怪的行为。我想使用 suspendCoroutine() 在我的项目中转换一些异步请求.这是显示此问题的一段代码。

在第一种情况下,当在 runBlocking 中调用挂起函数时协程,来自 continuation 的异常进入 catch 块,然后 runBlocking成功完成。但在第二种情况下,当创建新 async 时协程,异常通过 catch 块并使整个程序崩溃。

package com.example.lib

import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

object Test {
fun runSuccessfulCoroutine() {
runBlocking {
try {
Repository.fail()
} catch (ex: Throwable) {
println("Catching ex in runSuccessfulCoroutine(): $ex")
}
}
}

fun runFailingCoroutine() {
runBlocking {
try {
async { Repository.fail() }.await()
} catch (ex: Throwable) {
println("Catching ex in runFailingCoroutine(): $ex")
}
}
}
}

object Repository {
suspend fun fail(): Int = suspendCoroutine { cont ->
cont.resumeWithException(RuntimeException("Exception at ${Thread.currentThread().name}"))
}
}


fun main() {
Test.runSuccessfulCoroutine()
println()

Test.runFailingCoroutine()

println("We will never get here")
}

这就是控制台上打印的内容:
Catching ex in runSuccessfulCoroutine(): java.lang.RuntimeException: Exception at main

Catching ex in runFailingCoroutine(): java.lang.RuntimeException: Exception at main
Exception in thread "main" java.lang.RuntimeException: Exception at main
at com.example.lib.Repository.fail(MyClass.kt:32)
at com.example.lib.Test$runFailingCoroutine$1$1.invokeSuspend(MyClass.kt:22)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:236)
at kotlinx.coroutines.EventLoopBase.processNextEvent(EventLoop.kt:123)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:69)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:45)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:35)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at com.example.lib.Test.runFailingCoroutine(MyClass.kt:20)
at com.example.lib.MyClassKt.main(MyClass.kt:41)
at com.example.lib.MyClassKt.main(MyClass.kt)

Process finished with exit code 1

任何想法为什么会发生这种情况 - 这是一个错误,还是我以错误的方式使用协程?

更新:

使用 coroutineScope { ... }将缓解 runFailingCoroutine() 中的问题
fun runFailingCoroutine() = runBlocking {
try {
coroutineScope { async { fail() }.await() }
} catch (ex: Throwable) {
println("Catching ex in runFailingCoroutine(): $ex")
}
}

最佳答案

你的第二个例子的行为是正确的,这是结构化并发的工作。
因为内部async块抛出异常,这个协程被取消。由于结构化并发,父作业也被取消。

看这个小例子:

val result = coroutineScope {
async {
throw IllegalStateException()
}
10
}

这个块永远不会返回值,即使我们从不请求 async结果。内部协程被取消,外部作用域也被取消。

如果您不喜欢这种行为,您可以使用 supervisorScope .在这种情况下,内部协程可能会失败而不会使外部协程失败。
val result = supervisorScope {
async {
throw IllegalStateException()
}
10
}

在您的第一个示例中,您捕获了协程块内的异常,因此,协程正常退出。

有关此主题的讨论,请参见:
  • https://github.com/Kotlin/kotlinx.coroutines/issues/552
  • https://github.com/Kotlin/kotlinx.coroutines/issues/763
  • 关于exception - Kotlin 协程无法处理异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53238495/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com