问题描述
为什么此代码永远不会打印Hello World?
runBlocking(dispatchers.Main) {
launch {
delay(1)
println("Hello world")
}
}
但这会打印
runBlocking {
launch {
delay(1)
println("Hello world")
}
}
解决方法
在我看到的第一个示例中,该应用程序完全冻结了(当在按钮单击侦听器中使用时)。
问题是您造成了僵局:
-
Dispatchers.Main
通过将协程发布(调度)到主应用程序循环器中来工作 -
runBlocking
阻止主应用程序线程 - 主循环程序永远不会运行已发布的协程,因为它正在等待
runBlocking
完成
您可以使用Dispatchers.Main.immediate
来稍微缓解“问题”,它是基本调度程序的一个更聪明的版本-如果它已经在主线程上运行并在其中执行,它不会将协程发布到主循环程序中-地方。
这将允许您运行launch
块,但是delay
将再次发布协程以继续在主循环程序上执行并导致另一个死锁。
第二个代码示例没有问题,因为在那里运行的协程不与主线程进行交互(除了runBlocking
之外)。