是否有一种很好的方法让 channel 在关闭后忽略报价而不引发异常?

目前,由于isClosedForSend并不是原子的,因此似乎只有try catch才有效。

另外,如果我根本不关闭 channel ,是否有问题?
对于我的特定用例,我使用通道替代Android livedata(因为除了从任何线程发送值和从主线程侦听之外,我不需要任何其他好处)。在这种情况下,我可以通过仅在需要时发送值的生产者来监听通道,而忽略所有其他输入。

理想情况下,我有一个解决方案,其中ReceiveChannel仍然可以完成监听,但是在提供新值时SendChannel永远不会崩溃。

最佳答案

通道会抛出此异常by design,以作为正确通信的手段。

如果您绝对必须具有这样的内容,则可以使用这种扩展功能:

private suspend fun <E> Channel<E>.sendOrNothing(e: E) {
    try {
        this.send(e)
    }
    catch (closedException: ClosedSendChannelException) {
        println("It's fine")
    }
}

您可以使用以下代码对其进行测试:
val channel = Channel<Int>(capacity = 3)
    launch {

        try {
            for (i in 1..10) {
                channel.sendOrNothing(i)
                delay(50)
                if (i == 5) {
                    channel.close()
                }
            }

            println("Done")
        }
        catch (e: Exception) {
            e.printStackTrace()
        }
        finally {
            println("Finally")
        }
    }

    launch {
        for (c in channel) {
            println(c)
            delay(300)
        }
    }

您会注意到,由于关闭了通道,生产者将开始打印“很好”,但是消费者仍然可以读取前5个值。

关于第二个问题:这取决于。

通道没有这么大的开销,挂起的协程也没有。但是,泄漏就是泄漏,您知道的。

10-08 12:40
查看更多