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

时间:2019-01-14 23:00:54

标签: kotlin kotlinx.coroutines

有没有一种好方法让渠道在关闭后忽略商品而不会引发异常?

当前,似乎只有try catch才有效,因为isClosedForSend不是原子的。

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

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

2 个答案:

答案 0 :(得分: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个值。

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

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

答案 1 :(得分:0)

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

这更准确地反映了RxJava的PublishSubject

相关问题