kotlin - Kotlin coruntines 在启动和回调中不会执行
问题描述
在拿到这段代码之前,我以为我对 Kotlin 的协程已经足够熟悉了。
1 到 8 全部打印,除了 2:
import kotlinx.coroutines.*
import java.lang.Runnable
import java.lang.Thread.sleep
import kotlin.concurrent.thread
fun main() {
runBlocking {
Client.createAccount()
delay(1000)
}
}
object Client: CoroutineScope {
override val coroutineContext = newSingleThreadContext("Client")
fun createAccount() = launch {
Client2.init(Runnable {
println('1')
launch {
println('2')
}
ok()
ok2()
})
println('7')
launch {
println('8')
}
}
fun ok() {
println('3')
launch {
println('4')
}
}
fun ok2() = launch {
println('5')
launch {
println('6')
}
}
}
object Client2 {
fun init(runnable: Runnable) = thread {
sleep(100)
runnable.run()
}
}
结果是:
7
8
1
3
4
5
6
回调中的协程永远不会被调用。为什么?如果我删除1 到 8launch
中createAccount()
的将全部打印出来。此外,如果我使用GlobalScope.launch { println('2') }
而不是launch { println('2') }
,我也可以打印 2。
解决方案
原因是匿名类将其包装器范围用作父级。
launch { println('2') }
inRunnable { }
将在父作业createAccount()
启动完成时取消。
因此,它不能被调用,因为它会在launch { println('8') }
.
所以,如果你Client
像下面这样改变,它会正确打印“2”。
object Client: CoroutineScope {
override val coroutineContext = Dispatchers.Main
fun createAccount() = launch {
Client2.init(Run())
println("7")
launch {
println("8")
}
}
fun ok() {
println("3")
launch {
println("4")
}
}
fun ok2() = launch {
println("5")
launch {
println("6")
}
}
class Run: Runnable {
override fun run() {
println("1")
launch {
println("2")
}
ok()
ok2()
}
}
}
推荐阅读
- wix - wix Restart Manager 成功关闭应用程序但说它不能
- javascript - 如何在数组中的全名后添加逗号?
- java - 在 JDBC for PostgreSQL 中,我可以执行 psql 的命令吗?
- c# - 创建具有 Nullable 等行为的 C# 类或结构
- vba - 在 UDF 中处理可选参数的最佳方法是什么?
- alexa - 如何为 Alexa Skill 扩展自定义插槽类型?
- python-3.x - Python bot 删除消息
- javascript - 如何在 Web 浏览器中执行一些定期运行 FOREVER 的 Javascript 代码,并在每个时间间隔后更改 DOM
- excel - 按标题移动饼图点?
- pandas - Pandas:根据其他列值获取列的最大值