I'm trying to experiment with non-cancellable coroutines and I wrote the following code:
fun main(): Unit = runBlocking {
// launch first coroutine
coroutineScope {
val job1 = launch {
withContext(NonCancellable) {
val delay = Random.nextLong(from = 500, until = 5000)
println("Coroutine started. Waiting for ${delay}ms")
delay(delay)
println("Coroutine completed")
}
}
delay(300) // let it print the first line
println("Cancelling coroutine")
job1.cancelAndJoin()
}
}
Output:
Coroutine started. Waiting for 1313ms
Cancelling coroutine
Coroutine completed
So far, everything works as expected. However, if I pass the NonCancellable context (or rather, Job) directly in the launch function, the behaviour changes and the coroutine is cancelled:
fun main(): Unit = runBlocking {
// launch first coroutine
coroutineScope {
val job1 = launch(context = NonCancellable) {
val delay = Random.nextLong(from = 500, until = 5000)
println("Coroutine started. Waiting for ${delay}ms")
delay(delay)
println("Coroutine completed")
}
delay(300) // let it print the first line
println("Cancelling coroutine")
job1.cancelAndJoin()
}
}
Output:
Coroutine started. Waiting for 4996ms
Cancelling coroutine
Why is the second snippet producing a different output?