receiveCatching
Retrieves an element, removing it from the channel.
A difference from receive is that this function encapsulates a failure in its return value instead of throwing an exception. However, it will still throw CancellationException if the coroutine calling receiveCatching is cancelled.
It is guaranteed that the only way this function can return a failed result is when the channel is closed for receive
, so ChannelResult.isClosed is also true.
This function suspends if the channel is empty, waiting until an element is available or the channel becomes closed.
val channel = Channel<Int>()
launch {
while (true) {
val result = channel.receiveCatching() // suspends
when (val element = result.getOrNull()) {
null -> break // the channel is closed
else -> check(element == 5)
}
}
}
channel.send(5)
Suspending and cancellation
This suspending function is cancellable: if the Job of the current coroutine is cancelled while this suspending function is waiting, this function immediately resumes with CancellationException. There is a prompt cancellation guarantee: even if receiveCatching managed to retrieve the element from the channel, but was cancelled while suspended, CancellationException will be thrown, and, if the channel has an onUndeliveredElement
callback installed, the retrieved element will be passed to it. See the "Undelivered elements" section in the Channel documentation for details on handling undelivered elements. See suspendCancellableCoroutine for the low-level details of prompt cancellation.
Note that this function does not check for cancellation when it manages to immediately receive an element without suspending. Use ensureActive or CoroutineScope.isActive to periodically check for cancellation in tight loops if needed:
val channel = Channel<Int>()
launch { // a very fast producer
while (true) {
channel.send(42)
}
}
val consumer = launch { // a slow consumer
while (isActive) {
val element = channel.receiveCatching().getOrNull() ?: break
// some slow computation involving `element`
}
}
delay(100.milliseconds)
consumer.cancelAndJoin()
Receiving from a closed channel
Attempting to receiveCatching from a closed channel while there are still some elements will successfully retrieve an element from the channel.
When a channel is closed and there are no elements remaining, the channel becomes closed for
receive
. After that, receiveCatching will return a result with ChannelResult.isClosed set. ChannelResult.exceptionOrNull will be the exact (in the===
sense) exception that was passed to SendChannel.close, ornull
if none was given.
Related
This function can be used in select invocations with the onReceiveCatching clause. Use tryReceive to try receiving from this channel without waiting and throwing. Use receive to receive from this channel and throw exceptions on error.