Documentation for the delay function states: "This suspending function is cancellable. If the Job of the current coroutine is cancelled or completed while this suspending function is waiting, this function immediately resumes with CancellationException."
But I'm not seeing it throw a CancellationException. In fact the delay waits for the full 10 seconds before proceeding.
Why?
import kotlinx.coroutines.*
import java.util.concurrent.CancellationException
class MyClass {
private val scope = CoroutineScope(SupervisorJob() + CoroutineName("X coroutine"))
init {
scope.launch {
delay(500)
println("cancelling the scope")
scope.cancel(CancellationException("cancelling the scope"))
}
}
suspend fun callScopedFunction(
func: suspend CoroutineScope.() -> Int
): Int {
if (scope.isActive) {
println("callScopedFunction scope is active")
}
return scope.func()
}
}
fun main() {
runBlocking {
val result = MyClass().callScopedFunction {
println("coroutineContext.job.isCancelled: ${coroutineContext.job.isCancelled}")
delay(10000)
println("coroutineContext.job.isCancelled: ${coroutineContext.job.isCancelled}")
250
}
println(result)
}
}
Output:
callScopedFunction scope is active
coroutineContext.job.isCancelled: false
cancelling the scope
coroutineContext.job.isCancelled: true
250
You have never launched any coroutines in the scope that you cancel besides the initial one that cancels its own scope. Notice the
launchfunction is never used in your code anywhere else.scope.func()is essentially passingscopeas a parameter (this) to thefuncsuspend function, but it’s up to the implementing lambda to decide how to use it. And you didn’t use it at all in the lambda.Your
delay(10000)call is made within therunBlocking’s coroutine scope since this lambda is called from that scope.A corrected version would be something like this (but I didn’t test it):