Kotlin 协同路由作用域和异步正确的方法?

Kotlin 协同路由作用域和异步正确的方法?,kotlin,jvm,kotlin-coroutines,Kotlin,Jvm,Kotlin Coroutines,我喜欢协同例程的概念,我一直在我的android项目中使用。目前我正在开发一个JVM模块,我将把它包含在Ktor项目中,我知道Ktor支持协同例程 (查找附加的代码段) 我只是想知道这是正确的方法吗? 如何将异步与递归结合使用 你可以推荐任何能帮助我掌握更深入的co例程知识的资源都会很有帮助 提前谢谢 override suspend fun processInstruction(args.. ): List<Any> = coroutineScope { val dataWit

我喜欢协同例程的概念,我一直在我的android项目中使用。目前我正在开发一个JVM模块,我将把它包含在Ktor项目中,我知道Ktor支持协同例程

(查找附加的代码段)

我只是想知道这是正确的方法吗? 如何将异步与递归结合使用

你可以推荐任何能帮助我掌握更深入的co例程知识的资源都会很有帮助

提前谢谢

override suspend fun processInstruction(args.. ): List<Any> = coroutineScope {

 val dataWithFields = async{       
     listOfFields.fold(mutableList()){ acc,field ->
    val data = someProcess(field)
    val nested = processInstruction(...nestedField) // nested call

    acc.addAll(data)
    acc.addAll(nested)
    acc
}
}

return@coroutineScope postProcessData(dataWithFields.await())

}
override suspend-fun-processInstruction(args..):List=coroutineScope{
val dataWithFields=async{
fold(mutableList()){acc,字段->
val数据=someProcess(字段)
val nested=processInstruction(…nestedField)//嵌套调用
acc.addAll(数据)
acc.addAll(嵌套)
行政协调会
}
}
return@coroutineScope后处理数据(dataWithFields.await())
}

如果要并行处理所有嵌套调用,应将每个嵌套调用包装在
async
中(
async
应位于循环内部)。然后,在循环之后,您应该等待所有结果。(在您的代码中,您在single
async
之后立即运行
wait
,因此没有并行执行)

例如,如果您有
元素

interface Element {
    val subElements: List<Element>
    suspend fun calculateData(): SomeData
}

interface SomeData

正如您在评论部分所说,您需要父数据来计算子数据,因此
calculateAllData()
应该做的第一件事是计算父数据:

suspend fun Element.calculateAllData(
    parentData: SomeData = defaultParentData()
): List<SomeData> = coroutineScope {
    val data = calculateData(parentData)
    val subData = subElements.map { sub -> async { sub.calculateAllData(data) } }
    return@coroutineScope listOf(data) + subData.awaitAll().flatten()
}
以及以下测试:

println(measureTime {
    elmOf(
        elmOf(),
        elmOf(
            elmOf(),
            elmOf(
                elmOf(),
                elmOf(),
                elmOf()
            )
        ),
        elmOf(
            elmOf(),
            elmOf()
        ),
        elmOf()
    ).calculateAllData()
})

如果不需要父数据来计算子数据,它将打印
1.06s
,因为在这种情况下,所有数据都是并行计算的。否则,它将打印
4.15s
,因为元素树的高度是4。

这非常有用。如果子数据依赖于数据(意味着我们需要父元素信息来处理子元素),那么我应该在声明val data=async{calculateData()}之后立即调用wait,正如您所指出的,将不会有并行执行。在这种情况下,什么是有效的处理方法???@TechDrago从不在
async
之后立即调用
wait
。这是毫无意义的。只需从
val data=async{calculateData()}
中删除
async
,并从
data.await()
@TechDrago中删除
await
,如果按照我在前面的注释中所说的做,每个元素自己的数据将在子元素数据之前计算。但是子元素数据仍然会并行计算,因为
awaitAll
。嘿@Bananon如果某个数据从父计算返回一个值,我必须将该值提供给calculateData(在子元素上)。所以我不能说result.myvalue,因为它是一个延迟对象,类似这样:
async{calculateData(“硬编码值”)}
subElements.map{sub->async{sub.calculatealdata(“父操作的值(网络操作假设)”)}
谢谢,你的回答帮助我更好地理解了这个概念。
class ElementImpl(override val subElements: List<Element>) : Element {
    override suspend fun calculateData(parentData: SomeData): SomeData {
        delay(1000)
        return SomeData()
    }
}

fun elmOf(vararg elements: Element) = ElementImpl(listOf(*elements))
println(measureTime {
    elmOf(
        elmOf(),
        elmOf(
            elmOf(),
            elmOf(
                elmOf(),
                elmOf(),
                elmOf()
            )
        ),
        elmOf(
            elmOf(),
            elmOf()
        ),
        elmOf()
    ).calculateAllData()
})