我的服务器中有pusub订阅者,它运行并行任务,需要等待所有任务完成.

目前,当一个子元素抛出异常时,它会完全损坏整个订阅者,整个管道也会中断.

然后,我try 为"有问题"的子元素的CancellationExcept添加try-catch. 然而,然后我注意到,尽管订阅者do继续处理,但它并不会让订阅者等待所有任务.

       try {
            listOf(
                async {
                    // A - fails
                    delay(timeMillis(seconds = 0.5))
                    throw CancellationException()
                },
                async {
                    delay(timeMillis(seconds = 10))
                    println("B finished")
                },
                async {
                    delay(timeMillis(seconds = 5))
                    println("C finished")
                }
            ).awaitAll()
        } catch (e: CancellationException) {
            println("cancellation!")
        } catch (e: Throwable) {
            println("throwable!")
        }
        println("All finished -----------------")

我看到打印的是:

cancellation!
All finished -----------------
C finished
B finished

但我需要能够等到B和C完成,even if A失败/引发异常.

换句话说,我想要这种行为:

cancellation! (A fails)
C finished
B finished
All finished -----------------

如何才能实现这一目标?

推荐答案

要等待一组协同程序全部完成,无论是否失败,并且无需返回结果,请对每个协同程序使用supervisorScopelaunch.您可以使用CoroutineExceptionHandler来记录错误.

不要抛出取消按钮来代表您自己的失败.这可能会扰乱协程的工作方式.CancellationResponse是协程使用的一个特殊工具,用于使协程的及时取消发挥作用.

不要在不重新投掷的情况下抓住取消按钮.

因此更正后的代码看起来像:

supervisorScope {
    val handler = CoroutineExceptionHandler { _, e -> 
        println("throwable! $e") 
    }
    launch(handler) {
        // A - fails
        delay(timeMillis(seconds = 0.5))
        throw Exception("a failed")
    }
    launch(handler) {
        delay(timeMillis(seconds = 10))
        println("B finished")
    }
    launch(handler) {
        delay(timeMillis(seconds = 5))
        println("C finished")
    }
}

Kotlin相关问答推荐

直接从SON解析NonEmptyList

Kotlin—从列表中枚举属性计算不同值的数量

带有Spring Boot和Kotline的可嵌入实体

如何让 LocalDateTime.parse 拒绝 24:00 时间

协程子作业(job)取消

kotlin 父类具有依赖于抽象变量的变量

第二个协程永远不会执行

Mixin 在 Jackson 中添加 defaultImpl 不起作用

为什么没有remember 的 mutableStateOf 有时会起作用?

多次运行espresso测试

Kotlin 中列表或数组的乘积

Kotlin 协程中的 Dispatchers.Main 和 Dispatchers.Default 有什么区别?

如何退出 Kotlinc 命令行编译器

`DataBindingUtil` 中的 `bind`、`inflate` 和 `setContentView` 有什么区别

Foo::class.java 和 Foo::javaClass 有什么区别?

将协同路由调用放在存储库或ViewModel中哪个更好?

将多个 Kotlin 流合并到一个列表中,而无需等待第一个值

如何在kotlin语言中将字符转换为ascii值

Kotlin内联属性的用例是什么?

如何在 IntelliJ IDEA 中禁用粘贴时将 Java 转换为 Kotlin?