¿Hay una buena manera de que los canales ignoren las ofertas una vez cerradas sin generar una excepción?
Actualmente, parece que solo Try Catch funcionaría, ya que isClosedForSend no es atómico.
Alternativamente, ¿hay algún problema si simplemente nunca cierro un canal? Para mi caso de uso específico, estoy usando canales como una alternativa a los datos en vivo de Android (ya que no necesito ninguno de los beneficios más allá de enviar valores desde cualquier hilo y escuchar desde el hilo principal). En ese caso, podría escuchar el canal a través de un productor que solo envía valores cuando yo quiero y simplemente ignorar todas las demás entradas.
Idealmente, tendría una solución en la que ReceiveChannel todavía puede terminar de escuchar, pero donde SendChannel nunca fallará cuando se le ofrezca un nuevo valor.
Los canales lanzan esta excepción por diseño , como medio de comunicación correcta.
Si absolutamente debe tener algo como esto, puede usar una función de extensión de este tipo:
private suspend fun <E> Channel<E>.sendOrNothing(e: E) { try { this.send(e) } catch (closedException: ClosedSendChannelException) { println("It's fine") } }Puedes probarlo con el siguiente fragmento de código:
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) } }Como notará, el productor comenzará a imprimir "Está bien" ya que el canal está cerrado, pero el consumidor aún podrá leer los primeros 5 valores.
En cuanto a tu segunda pregunta: depende.
Los canales no tienen una sobrecarga tan grande, y tampoco las rutinas suspendidas. Pero una fuga es una fuga, ya sabes.
Terminé publicando un problema en el repositorio y la solución fue usar BroadcastChannel . Puede crear un nuevo ReceiveChannel a través de openSubscription , donde cerrarlo no cerrará SendChannel .
Esto refleja con mayor precisión el PublishSubject de PublishSubject