Cooperative Cancellation

Code Must Check

Cancellation is cooperative: a coroutine stops only when it reaches a suspension point or checks for cancellation. A tight CPU loop that never suspends will ignore cancel().

Example

The first loop never checks, so it runs all 5 steps even after cancel. The second calls ensureActive() and stops.

import kotlinx.coroutines.*

fun main() = runBlocking {
    val ignoring = launch(Dispatchers.Default) {
        for (step in 0 until 5) {
            Thread.sleep(100)                 // CPU / blocking work, no suspension
            println("ignoring: step $step")
        }
    }
    delay(250)
    ignoring.cancelAndJoin()
    println("--- first job ended")

    val cooperative = launch(Dispatchers.Default) {
        for (step in 0 until 5) {
            ensureActive()                    // throws if cancelled
            Thread.sleep(100)
            println("cooperative: step $step")
        }
    }
    delay(250)
    cooperative.cancelAndJoin()
    println("--- second job ended")
}

Output

ignoring: step 0
ignoring: step 1
ignoring: step 2
ignoring: step 3
ignoring: step 4
--- first job ended
cooperative: step 0
cooperative: step 1
cooperative: step 2
--- second job ended

Three Ways to Check

CheckBehaviour
isActiveproperty: while (isActive) { ... }, you decide how to stop
ensureActive()throws CancellationException if cancelled
yield()checks cancellation and lets other coroutines on the same dispatcher run

Tip: In long loops (parsing a big file, processing 1 lakh rows) call ensureActive() every iteration or every N items.