关闭后忽略协程通道的报价

Ignoring offers to coroutine channels after closing

是否有一种好方法可以让频道在关闭后忽略优惠而不抛出异常?

目前,似乎只有 try catch 可以工作,因为 isClosedForSend 不是原子的。

或者,如果我根本不关闭频道会有问题吗? 对于我的特定用例,我使用通道作为 Android 实时数据的替代方案(因为除了从任何线程发送值和从主线程监听之外,我不需要任何好处)。在那种情况下,我可以通过只在我想要时发送值的生产者收听频道,而忽略所有其他输入。

理想情况下,我有一个解决方案,其中 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)
        }
    }

您会注意到,由于通道关闭,生产者将开始打印 "It's fine",但消费者仍将能够读取前 5 个值。

关于你的第二个问题:视情况而定。

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

我最终将 an issue 发布到存储库,解决方案是使用 BroadcastChannel。您可以通过 openSubscription 创建一个新的 ReceiveChannel,关闭它不会关闭 SendChannel

这更准确地反映了 RxJava 的 PublishSubject