Каналы выбрасывают это исключение по схеме , как средство правильной связи.
Если вам абсолютно необходимо иметь что-то подобное, вы можете использовать функцию расширения такого рода:
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 значений.
Относительно вашего второго вопроса: это зависит.
Каналы не имеют таких больших накладных расходов, как и приостановленные сопрограммы. Но утечка - это утечка, вы знаете.