关闭后忽略对coroutine通道的提议

问题描述 投票:1回答:2

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

目前,似乎只有尝试捕获才能起作用,因为isClosedForSend不是原子的。

或者,如果我根本不关闭某个频道,是否会出现问题?对于我的特定用例,我使用渠道作为Android liveata的替代品(因为除了从任何线程发送值并从主线程中侦听之外,我不需要任何其他好处)。在这种情况下,我可以通过生产者来监听频道,该生产者只在我想要的时候发送值,并且只是忽略所有其他输入。

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

kotlin kotlinx.coroutines
2个回答
0
投票

渠道抛出这个例外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个值。

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

频道没有这么大的开销,也没有暂停的协同程序。但是你知道,泄漏是泄漏。


0
投票

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

这更准确地反映了RxJava的PublishSubject

© www.soinside.com 2019 - 2024. All rights reserved.