如何在使用当前父作用域的“suspend fun”中启动Kotlin协同程序?

如何在使用当前父作用域的“suspend fun”中启动Kotlin协同程序?,kotlin,kotlinx.coroutines,Kotlin,Kotlinx.coroutines,如何从挂起函数启动协同路由并使其使用当前作用域?(因此,在启动的协同程序也结束之前,作用域不会结束) 我想写一些如下的东西—— import kotlinx.coroutines.* fun main() = runBlocking { // this: CoroutineScope go() } suspend fun go() { launch { println("go!") } } 但这有一个语法错误:“未解析引用:启动”。看来launch必

如何从挂起函数启动协同路由并使其使用当前作用域?(因此,在启动的协同程序也结束之前,作用域不会结束)

我想写一些如下的东西——

import kotlinx.coroutines.*

fun main() = runBlocking { // this: CoroutineScope
    go()
}

suspend fun go() {
    launch {
        println("go!")
    }
}
但这有一个语法错误:“未解析引用:启动”。看来
launch
必须以以下方式之一运行-

GlobalScope.launch {
    println("Go!")
}

这些选择都不能满足我的需要。要么代码“阻塞”而不是“繁殖”,要么它繁殖,但父作用域不会在父作用域本身结束之前等待其完成

我需要它在当前父协同程序作用域中“生成”(启动),父协同程序作用域应该等待生成的协同程序完成,然后再结束自身

我希望在一个
suspend fun
中的一个简单的
launch
将是有效的,并使用它的父范围


我正在使用
Kotlin 1.3
cotlinx coroutines core:1.0.1
我相信我找到了一个解决方案,它是
和(CoroutineScope(coroutineContext)
。下面的示例说明了这一点-

import kotlinx.coroutines.*

fun main() = runBlocking {
    go()
    go()
    go()
    println("End")
}

suspend fun go() {
//  GlobalScope.launch {                     // spawns, but doesn't use parent scope
//  runBlocking {                            // blocks
//  withContext(Dispatchers.Default) {       // blocks
//  coroutineScope {                         // blocks
    with(CoroutineScope(coroutineContext)) { // spawns and uses parent scope!
        launch {
            delay(2000L)
            println("Go!")
        }
    }
}

但是,Rene在上面发布了一个更好的解决方案。

您应该将函数
go
作为
CoroutineScope
的扩展函数:

fun main() = runBlocking {
    go()
    go()
    go()
    println("End")
}

fun CoroutineScope.go() = launch {
    println("go!")
}
阅读本文,了解为什么在不创建新的
coroutineScope{}
的情况下启动
suspend
函数和其他协同例程不是一个好主意

约定是:在
挂起
函数中,如果需要启动并行协同路由,则调用其他
挂起
函数并创建一个新的
协同路由
。结果是,只有当所有新启动的协同路由完成时(结构化并发),协同路由才会返回


另一方面,如果您需要在不知道作用域的情况下启动新的协同路由,您可以创建一个扩展函数
CoroutineScope
,它本身不是
suspendable
。现在调用方可以决定应该使用哪个作用域。

这是可行的,但有点倒退。它使用全局
suspend val coroutineContext
并用它实例化一个
CoroutineScope
。为什么不声明
suspend-fun-CoroutineScope.go()
,这是推荐的方法?另外,你确定你需要
go()
成为一个
suspend-fun
?它实际上不会挂起。让它成为
fun-CoroutineScope.go()
更干净,不,它不需要是一个
暂停乐趣
。我只是想了解一下Kotlin的合作项目,谢谢。
coroutineScope {
    launch {
        println("Go!")
    }
}
import kotlinx.coroutines.*

fun main() = runBlocking {
    go()
    go()
    go()
    println("End")
}

suspend fun go() {
//  GlobalScope.launch {                     // spawns, but doesn't use parent scope
//  runBlocking {                            // blocks
//  withContext(Dispatchers.Default) {       // blocks
//  coroutineScope {                         // blocks
    with(CoroutineScope(coroutineContext)) { // spawns and uses parent scope!
        launch {
            delay(2000L)
            println("Go!")
        }
    }
}
fun main() = runBlocking {
    go()
    go()
    go()
    println("End")
}

fun CoroutineScope.go() = launch {
    println("go!")
}