0Pricing
Kotlin Academy · Leçon

Propagation de l’annulation dans les hiérarchies de coroutines

Comprenez comment l’annulation se propage dans les relations entre coroutines parentes et enfants.

Propagation de l’annulation dans les hiérarchies de coroutines est une leçon Kotlin Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Kotlin Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Kotlin Academy comprend 4 leçons au total.

Relation parent-enfant

Lorsqu'une coroutine en lance une autre avec launch, l'enfant rejoint le Job du parent. L'annulation du parent annule tous les enfants.

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")
}

L'échec d'un enfant annule le parent

Si un enfant lève une exception autre qu'une annulation, il annule le parent et tous ses frères et sœurs — c'est le comportement par défaut 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}")
    }
}

L'annulation ne se propage pas vers le parent

L'annulation d'un enfant n'annule PAS le parent. Seules les exceptions non gérées le font. Un parent peut annuler un enfant à tout moment.

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 et GlobalScope

coroutineScope crée une portée enfant : l'annulation et les erreurs se propagent. GlobalScope crée des coroutines orphelines sans parent — évitez-le en production.

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
}

Annuler un sous-arbre

Chaque appel à launch ou async renvoie un Job. Annulez un travail pour annuler tout son sous-arbre, y compris les lancements imbriqués.

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() après cancel()

Appelez toujours join() après cancel() pour attendre que la coroutine et ses enfants se soient complètement arrêtés avant de continuer.

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() est un raccourci pratique qui annule puis attend, ce qui équivaut à 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")
}

Propagation avec async

Avec async, les exceptions sont stockées dans le Deferred et levées lorsque vous appelez await(). Elles se propagent néanmoins au parent si elles ne sont pas interceptées.

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}")
    }
}

Garantie de la concurrence structurée

La concurrence structurée garantit que lorsque la portée s'achève, tous ses enfants sont terminés. Aucune coroutine ne fuit : soit elle s'achève, soit elle est annulée.

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")
}

Diagramme de propagation de l'annulation

La hiérarchie : cancel du parent → tous les enfants annulés. Annulation de l'enfant → uniquement son sous-arbre. Exception de l'enfant → parent annulé → frères et sœurs annulés.

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()
}

Cycle de vie de CoroutineScope dans Android

Dans Android, viewModelScope est annulée lorsque le ViewModel est effacé. Toutes les coroutines lancées sont annulées automatiquement — aucun nettoyage manuel n'est nécessaire.

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()") }

Vérification rapide

Que deviennent les coroutines sœurs lorsqu'un enfant lève une exception non gérée sous un Job normal ?

Récapitulatif

L'annulation du parent se propage en cascade à tous les enfants. L'échec d'un enfant se propage au parent et aux frères et sœurs (avec un Job normal). Utilisez cancelAndJoin() pour un arrêt propre. La concurrence structurée garantit l'absence de fuites de coroutines.

Questions Fréquemment Posées

La leçon « Propagation de l’annulation dans les hiérarchies de coroutines » est-elle gratuite ?

Oui — le texte complet de « Propagation de l’annulation dans les hiérarchies de coroutines » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Kotlin Academy, passe à CoddyKit PRO. Le cours Kotlin Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Propagation de l’annulation dans les hiérarchies de coroutines » ?

Comprenez comment l’annulation se propage dans les relations entre coroutines parentes et enfants. Tu pratiques Kotlin Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Kotlin Academy ?

Aucune expérience préalable n'est requise. Kotlin Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.

Combien de temps prend la leçon « Propagation de l’annulation dans les hiérarchies de coroutines » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Kotlin Academy ?

Oui. Chaque leçon Kotlin Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Annulation coopérative : isActive et ensureActive
  2. withTimeout et withTimeoutOrNull
  3. Nettoyage avec finally et NonCancellable
  4. Propagation de l’annulation dans les hiérarchies de coroutines
← Retour à Kotlin Academy