If I have a coroutine that contains a withContext(NonCancellable) {}
block, and said coroutine is cancelled while execution is inside that block, what is supposed to happen?
I tried this in my code, and expected that the cancellation is somehow “remembered” after the NonCancellable
block is finished. That is - as soon as the block is left, the coroutine stops. But instead, it appears to me that the cancellation is somehow forgotten, as if that block caused it to be dropped…
Does anybody know more? I even tried to check isActive
and isCancelled
, and both were true and false, respectively.
2 Likes
When you call withContext
with a Job
(like NonCancellable
, it simply replaces any previous Job
in the new CoroutineContext
.
The new CoroutineContext
has no relationship with the old Job
.
When you cancel NonCancellable
, it simply ignores the call. If you want to cancel the previous Job
/CoroutineScope
you need to cancel it directly.
But this only affects the code within the withContext block, not the code outside of it, right?
Example:
val job = launch {
withContext(NonCancellable) {
// ...
}
delay(10000)
}
If some other code calls job.cancel()
while the coroutine is currently running the block inside withContext
, then after that block is finished, the delay
call still should exit immediately because job
was cancelled, right?
1 Like
Yes-ish. Technically, the withContext
will run to completion and then resume with a CancellationException
so delay
won’t event be called. This is referred to in the docs as a “prompt cancellation guarantee”.
The docs have pretty detailed info about what happens in this case: withContext