Anton Kapelyushok
05/19/2023, 5:39 PMTrevor Stone
05/19/2023, 6:09 PMcancel()
is called on a CoroutineScope
. The this
being called on is the surrounding launch
. When this happens the flow is going to stop collecting, but the other launched coroutine scope is unaffected. The flow will stop collecting and call close on the channel, but according to the docs
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.
When you call coroutineScope { cancel() }
what actually is happening is you are using the suspend
block inside of collect, creating a coroutine scope, and calling cancel on that. That scope cancellation will then propagate up the suspending function calls.
To prove this, add a delay(100)
between the channel send, and use the cancel() version. You should see your expected errorTrevor Stone
05/19/2023, 6:10 PMTrevor Stone
05/19/2023, 6:12 PMcancel()
being called on the launch's coroutinescope. Using coroutineScope{cancel()}
cancels the suspending function immediately so the second send doesn't get to suspendAnton Kapelyushok
05/19/2023, 6:19 PMcoroutineScope{cancel()}
ProducerCoroutine gets canceled, which leads to channel.cancel()
call which wakens up suspended channel.send()
in case with cancel()
call, launch
coroutine gets canceled, which then cancels all its children, in this case ProducerCoroutine, but it calls channel.close()
instead, which has no effect on suspended channel.send()
Trevor Stone
05/19/2023, 8:16 PM