You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin挂起函数调用Channel.send阻塞,无法获取Flow首个值求助

Kotlin挂起函数获取Flow首个值时send阻塞的原因

我编写了一个Kotlin挂起函数readSensorTemperature,目的是获取Flow的第一个值并返回,但程序在执行ch.send(st)时发生阻塞。相关代码如下:

private suspend fun readSensorTemperature(): Double {
    val ch = Channel<Double>()

    val job = coroutineScope {
        launch {
            myFlow.collect { st ->
                ch.send(st)
            }
        }
    }

    val res = ch.receive()
    job.cancel()

    return res
}

(注:原代码中st -为笔误,已修正为st ->)

问题原因分析

核心问题是协程作用域的等待逻辑导致了死锁:

  • coroutineScope的特性是必须等待所有子协程执行完成后,才会继续执行后续代码。而子协程内的myFlow.collect是持续收集Flow数据的操作(除非Flow主动结束),这就导致主协程一直卡在coroutineScope调用处,永远走不到ch.receive()这一步。
  • 默认的Channel是无缓冲的,ch.send(st)会挂起,直到有其他协程调用ch.receive()接收数据。现在子协程卡在send等待接收方,主协程卡在coroutineScope等待子协程结束,形成互相阻塞的死锁。

正确实现方式

Flow本身提供了first()操作符,可以直接获取第一个发射的值,完全不需要手动用Channel实现:

private suspend fun readSensorTemperature(): Double {
    return myFlow.first()
}

如果一定要手动实现类似逻辑,需要避免coroutineScope的等待,直接启动子协程即可:

private suspend fun readSensorTemperature(): Double {
    val ch = Channel<Double>()
    val job = launch {
        try {
            myFlow.collect { st ->
                ch.send(st)
                // 拿到第一个值后停止收集
                return@collect
            }
        } finally {
            ch.close()
        }
    }
    val res = ch.receive()
    job.cancel()
    return res
}

内容的提问来源于stack exchange,提问作者Solvek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 23:42:52