首页 > 解决方案 > 为什么 kotlin 协程会阻塞这段代码?

问题描述

为什么这段代码永远不会打印 Hello World?

runBlocking(Dispatchers.Main) {
    launch {
        delay(1)
        println("Hello world")
    }
}

但这会打印

runBlocking {
    launch {
        delay(1)
        println("Hello world")
    }
}

标签: androidkotlinkotlin-coroutines

解决方案


从我看到的第一个示例完全冻结应用程序(在按钮单击侦听器中使用时)。

问题是你造成了死锁:

  1. Dispatchers.Main通过将协程发布(调度)到主应用程序循环器来工作
  2. runBlocking阻塞主应用程序线程
  3. main looper 永远不会运行发布的协程,因为它正在等待runBlocking完成

您可以通过使用更智能的基本调度程序版本来稍微缓解“问题” Dispatchers.Main.immediate- 如果它已经在主线程上运行并就地执行它,它不会将协程发布到主循环器。

这将允许您运行该launch块,但delay将再次发布协程以在主循环器上继续并导致另一个死锁。

第二个代码示例没有问题,因为在那里运行的协程不与主线程交互(除此之外runBlocking)。


推荐阅读