如何在使用当前父作用域的“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!")
}