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?