我正在try 理解Kotlin中的 struct 化并发,但我无法理解这段代码.

fun main(): Unit = runBlocking {
    other(this)
}

suspend fun other(scope: CoroutineScope) {
    val job = scope.launch {
        scope.launch {
            delay(200)
            println("e")
        }
        println("a")
    }
    job.invokeOnCompletion {
        println("Complete")
    }
}

代码打印出来

a
Complete
e

而如果我将内部的scope.launch呼叫替换为launch,如下所示

suspend fun other(scope: CoroutineScope) {
    val job = scope.launch {
       launch {
            delay(200)
            println("e")
        }
        println("a")
    }
    job.invokeOnCompletion {
        println("Complete")
    }
}

它是打印的

a
e
Complete

这表明第一个示例不遵循 struct 化并发,因为父作业(job)先于子作业(job)完成.我的困惑是,为什么会发生这种情况?

我觉得在这种情况下,scope.launch可能相当于呼叫launch(应该相当于this.launch,这指的是scope).但这似乎不是真的.有人能解释一下为什么第一次调用会导致非 struct 化并发吗?两次启动调用之间有什么不同?谢谢!

推荐答案

在第一个代码中,虽然内部emits 看起来像是外部emits 的子级,但实际上不是--它是外部emits 的sibling ,因为它们都是从相同的范围emits 的.因此,等待外部emits 任务完成并不是等待内部emits 任务完成.

第二个代码使用 struct 化并发,因为内部启动使用外部启动创建的作用域(启动块的接收器).在本例中,它是外部启动的子级,因此等待外部任务完成也是等待子级完成.

第二个是您应该做的:使用启动块的CoroutineScope接收器来启动子作业(job).相反,使用其他作用域不会提供 struct 化并发.

Kotlin相关问答推荐

在没有外部 map 的情况下转换列表项

Jetpack Compose中的数字 Select 器问题

在KMM合成多平台中创建特定于平台的视图

在Kotlin 有更好的结合方式?

为什么可组合对象看似无状态(唯一传递的参数是函数,而不是状态),但会进行重组

使用 Kotlin 的 Springboot 中缺少 ResponseEntity 正文属性

Kotlin .如何用从 1 到 90 的 5 个唯一数字填充列表中的每一行?

MyType.()在 Kotlin 中是什么意思?

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

内容更改后的 var 重新计算

Jetpack Compose - 单击 LazyColumn 的项目时应用程序崩溃

如何连接两个 kotlin 流?

如何禁用智能投射突出显示 Kotlin?

Kotlin-Java 互操作不能与可变参数一起使用

用mockk验证属性设置程序吗?

在Kotlin中使用@Service时引发异常

用于代码生成的ANTLR工具版本4.7.1与当前运行时版本4.5.3不匹配

具有泛型param的Kotlin抽象类和使用类型param的方法

Kotlin中的嵌套let块

Android Jetpack Compose - 图像无法zoom 到框的宽度和高度