I have code that tries to send to a channel within a callback that isn’t a suspend function. I use runBlocking for this, along with a SupervisorJob. Example:
val job = SupervisorJob()
val channel = Channel()
[...]
fun onEvent() {
runBlocking {
try {
withContext(job) {
channel.send(someData)
}
} catch (_: CancellationException) {
// don't propagate cancellation; let runBlocking finish gracefully
} catch (_: ClosedSendChannelException) {
}
}
}
[...]
// When shutting down, I do this:
channel.close()
job.cancel()
I am focusing on the withContext block here. As the send() documentation states:
Closing a channel after this function has suspended does not cause this suspended send invocation to abort, because closing a channel is conceptually like sending a special “close token” over this channel.
The job.cancel() call is intended to handle the case where the send() call is already suspended. The outer try-catch block then catches the CancellationException to avoid an error in runBlocking. ClosedSendChannelException is also caught in case the channel got closed before send() was called.
Now, is this okay? Or are there better ways to cancel such a suspending function call that runs inside a runBlocking block?