0Pricing
Kotlin Academy · Lección

Propagación de la cancelación en jerarquías de corrutinas

Comprenda cómo fluye la cancelación en las relaciones entre corrutinas padre e hijas.

Propagación de la cancelación en jerarquías de corrutinas es una lección gratuita de Kotlin Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Kotlin Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Kotlin Academy incluye 4 lecciones en total.

Relación entre padre e hijo

Cuando una corrutina inicia otra con launch, la hija se incorpora al Job del padre. Al cancelar el padre, se cancelan todas las hijas.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val parent = launch {
        launch { delay(1000); println("child 1") }
        launch { delay(1000); println("child 2") }
        delay(1000)
        println("parent")
    }
    delay(50)
    parent.cancel()
    parent.join()
    println("All cancelled")
}

El fallo de una hija cancela al padre

Si una hija lanza una excepción que no es de cancelación, cancela al padre y a todas sus hermanas; este es el comportamiento predeterminado de Job.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        coroutineScope {
            launch {
                delay(50)
                throw RuntimeException("child failed")
            }
            launch {
                delay(1000)
                println("sibling — never prints")
            }
        }
    } catch (e: RuntimeException) {
        println("Caught: ${e.message}")
    }
}

La cancelación no se propaga hacia arriba

La cancelación de una hija NO cancela al padre. Solo lo hacen las excepciones no controladas. Un padre puede cancelar una hija cuando lo necesite.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val parent = launch {
        val child = launch {
            delay(1000)
            println("child done")
        }
        delay(50)
        child.cancel()  // cancels child
        child.join()
        println("parent still running")  // parent is fine
    }
    parent.join()
}

coroutineScope frente a GlobalScope

coroutineScope crea un ámbito hijo: la cancelación y los errores se propagan. GlobalScope crea corrutinas huérfanas sin padre; evítelo en producción.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        coroutineScope {
            launch { delay(50); throw RuntimeException("error") }
        }
    } catch (e: Exception) {
        println("coroutineScope propagated: ${e.message}")
    }
    // GlobalScope.launch { } would NOT propagate to runBlocking
}

Cancelación de un subárbol

Cada launch o async devuelve un Job. Cancele un trabajo para cancelar todo su subárbol, incluidos los lanzamientos anidados.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val root = launch {
        launch {
            launch { delay(1000); println("deep") }
            delay(1000)
        }
    }
    delay(50)
    root.cancel()
    root.join()
    println("Whole subtree cancelled")
}

join() después de cancel()

Llame siempre a join() después de cancel() para esperar a que la corrutina y sus hijas se detengan por completo antes de continuar.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try { delay(1000) }
        finally { println("cleanup ran") }
    }
    delay(50)
    job.cancel()
    job.join()  // waits for finally to complete
    println("Proceeded after join")
}

cancelAndJoin()

job.cancelAndJoin() es una función de conveniencia que cancela y después espera a que termine, equivalente a cancel() + join().

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try { delay(1000) }
        finally { println("cleanup") }
    }
    delay(50)
    job.cancelAndJoin()  // cancel + join in one call
    println("Done")
}

Propagación mediante async

Con async, las excepciones se almacenan en Deferred y se lanzan al llamar a await(). Aun así, se propagan al padre si no se controlan.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        coroutineScope {
            val d = async { throw RuntimeException("async fail") }
            d.await()  // rethrows here
        }
    } catch (e: RuntimeException) {
        println("Caught from async: ${e.message}")
    }
}

Garantía de la concurrencia estructurada

La concurrencia estructurada garantiza que, cuando un ámbito termina, todas sus hijas han terminado. No se producen fugas de corrutinas: o bien se completan o bien se cancelan.

import kotlinx.coroutines.*
suspend fun doWork() = coroutineScope {
    launch { delay(100); println("work 1") }
    launch { delay(200); println("work 2") }
    // both children complete before doWork returns
}
fun main() = runBlocking {
    doWork()
    println("All work done")
}

Diagrama de propagación de la cancelación

La jerarquía: cancelación del padre → todas las hijas canceladas. Cancelación de una hija → solo ese subárbol. Excepción de una hija → padre cancelado → hermanas canceladas.

import kotlinx.coroutines.*
fun main() = runBlocking {
    // Parent
    launch {
        val c1 = launch { delay(1000); println("c1") }  // child 1
        val c2 = launch { delay(1000); println("c2") }  // child 2
        delay(50)
        c1.cancel()  // only c1 cancelled
        c1.join()
        println("c2 still active: ${c2.isActive}")
        c2.cancelAndJoin()
    }.join()
}

Ciclo de vida de CoroutineScope en Android

En Android, viewModelScope se cancela cuando se elimina el ViewModel. Todas las corrutinas iniciadas se cancelan automáticamente; no se necesita una limpieza manual.

import kotlinx.coroutines.*
// Pseudocode:
// class MyViewModel : ViewModel() {
//     fun load() = viewModelScope.launch {
//         val data = repo.fetch() // cancelled if VM cleared
//         _state.value = data
//     }
// }
fun main() = runBlocking { println("viewModelScope cancels on ViewModel.onCleared()") }

Comprobación rápida

¿Qué ocurre con las corrutinas hermanas cuando una hija lanza una excepción no controlada bajo un Job normal?

Resumen

La cancelación del padre se propaga en cascada a todas las hijas. El fallo de una hija se propaga al padre y a las hermanas con un Job normal. Use cancelAndJoin() para desmontar todo correctamente. La concurrencia estructurada garantiza que no haya fugas de corrutinas.

Preguntas frecuentes

¿La lección «Propagación de la cancelación en jerarquías de corrutinas» es gratis?

Sí — el texto completo de «Propagación de la cancelación en jerarquías de corrutinas» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Kotlin Academy, actualiza a CoddyKit PRO. El curso de Kotlin Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Propagación de la cancelación en jerarquías de corrutinas»?

Comprenda cómo fluye la cancelación en las relaciones entre corrutinas padre e hijas. Practicas Kotlin Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Kotlin Academy?

No se requiere experiencia previa. Kotlin Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «Propagación de la cancelación en jerarquías de corrutinas»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Kotlin Academy?

Sí. Cada lección de Kotlin Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Cancelación cooperativa: isActive y ensureActive
  2. withTimeout y withTimeoutOrNull
  3. Limpieza con finally y NonCancellable
  4. Propagación de la cancelación en jerarquías de corrutinas
← Volver a Kotlin Academy