Kotlin Academy · Leçon

Nettoyage avec finally et NonCancellable

Libérez les ressources dans les coroutines annulées avec finally et withContext(NonCancellable).

Leçon 3 sur 413 étapes

Nettoyage avec finally et NonCancellable est une leçon Kotlin Academy gratuite sur CoddyKit. Ceci est la leçon 3 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.

Annulation et finally

Lorsqu'une coroutine est annulée, les points de suspension lèvent CancellationException. Le code des blocs finally s'exécute toujours — mais finally lui-même s'exécute dans un contexte de coroutine déjà annulé.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try {
            delay(1000)
        } finally {
            println("finally: cleaning up")
        }
    }
    delay(50)
    job.cancel()
    job.join()
}

Problème : suspension dans finally

Si vous essayez d'appeler delay ou d'effectuer une autre suspension dans finally d'une coroutine annulée, l'appel échoue immédiatement, car le contexte est déjà annulé.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try {
            delay(1000)
        } finally {
            // delay(100) // throws CancellationException here!
            println("Sync cleanup OK; async cleanup needs NonCancellable")
        }
    }
    delay(50); job.cancel(); job.join()
}

withContext(NonCancellable)

Entourez les appels de suspension dans finally avec withContext(NonCancellable) afin de les exécuter dans un contexte qui ne peut pas être annulé, même après l'annulation du parent.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try {
            delay(1000)
        } finally {
            withContext(NonCancellable) {
                delay(100)  // OK: runs despite cancellation
                println("Async cleanup complete")
            }
        }
    }
    delay(50); job.cancel(); job.join()
}

Quand utiliser NonCancellable

Utilisez NonCancellable pour fermer les connexions à la base de données, vider les journaux, envoyer des événements d'analyse ou effectuer tout nettoyage asynchrone qui doit s'achever quelle que soit l'annulation.

import kotlinx.coroutines.*
suspend fun closeConnection() {
    println("Closing DB connection...")
    delay(50) // simulate async close
    println("Connection closed")
}
fun main() = runBlocking {
    val job = launch {
        try { delay(1000) }
        finally { withContext(NonCancellable) { closeConnection() } }
    }
    delay(50); job.cancel(); job.join()
}

NonCancellable n'est pas une portée

NonCancellable est un Job que vous pouvez transmettre à withContext. Ne l'utilisez pas directement comme portée de coroutine — utilisez-le uniquement pour le nettoyage dans finally.

import kotlinx.coroutines.*
fun main() = runBlocking {
    // WRONG usage:
    // launch(NonCancellable) { ... } // launches a coroutine that cannot be cancelled
    // RIGHT usage:
    launch {
        try { delay(500) }
        finally {
            withContext(NonCancellable) {
                println("Safe cleanup")
            }
        }
    }.also { delay(50); it.cancel(); it.join() }
}

Nettoyage de plusieurs ressources

Enchaînez plusieurs opérations de nettoyage dans un seul bloc withContext(NonCancellable).

import kotlinx.coroutines.*
fun main() = runBlocking {
    launch {
        try {
            delay(1000)
        } finally {
            withContext(NonCancellable) {
                delay(20); println("Step 1: flush cache")
                delay(20); println("Step 2: close socket")
                delay(20); println("Step 3: log audit")
            }
        }
    }.also { delay(50); it.cancel(); it.join() }
}

Modèle de gestion des erreurs et du nettoyage

Associez la gestion des erreurs métier au nettoyage dans finally — c'est le modèle structuré standard.

import kotlinx.coroutines.*
fun main() = runBlocking {
    launch {
        try {
            delay(100)
            throw RuntimeException("business error")
        } catch (e: RuntimeException) {
            println("Handling: ${e.message}")
        } finally {
            withContext(NonCancellable) {
                println("Always cleanup")
            }
        }
    }.join()
}

Ordre du nettoyage

Les blocs finally s'exécutent dans l'ordre inverse de leur imbrication. Le bloc externe de gestion et de nettoyage s'exécute après les blocs internes, comme dans du code Java/Kotlin ordinaire.

import kotlinx.coroutines.*
fun main() = runBlocking {
    launch {
        try {
            try {
                delay(1000)
            } finally { println("Inner cleanup") }
        } finally { println("Outer cleanup") }
    }.also { delay(50); it.cancel(); it.join() }
}

Utilisation des ressources AutoCloseable

Pour les ressources AutoCloseable, utilisez l'extension Kotlin use { }, qui appelle automatiquement close(), même en cas d'exception ou d'annulation.

import kotlinx.coroutines.*
class Connection : AutoCloseable {
    init { println("Opened") }
    override fun close() { println("Closed") }
    suspend fun query(): String { delay(50); return "result" }
}
fun main() = runBlocking {
    val result = Connection().use { it.query() }
    println(result)
}

Journalisation de la raison de l'annulation

Récupérez le message d'annulation de CancellationException dans catch ou finally afin de journaliser la raison pour laquelle une coroutine s'est arrêtée.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try {
            delay(1000)
        } catch (e: CancellationException) {
            println("Cancelled: ${e.message}")
            throw e
        }
    }
    delay(50)
    job.cancel("user navigated away")
    job.join()
}

Nettoyage de CoroutineScope avec invokeOnCompletion

Job.invokeOnCompletion enregistre un rappel qui s'exécute lorsque le travail se termine, quelle qu'en soit la raison — une autre solution que finally pour le nettoyage au niveau du parent.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        delay(1000)
    }
    job.invokeOnCompletion { cause ->
        if (cause != null) println("Ended with: ${cause::class.simpleName}")
        else println("Completed normally")
    }
    delay(50)
    job.cancel()
    job.join()
}

Vérification rapide

Quel est le rôle de withContext(NonCancellable) dans un bloc finally ?

Récapitulatif

finally s'exécute toujours lors d'une annulation. Entourez les appels de suspension dans finally avec withContext(NonCancellable) afin qu'ils s'achèvent malgré l'annulation. Utilisez use { } pour les ressources AutoCloseable.

Gratuit pour commencer

Apprends Kotlin avec un tuteur IA — gratuit

Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.

Cours
51
Leçons
203

Questions Fréquemment Posées

La leçon « Nettoyage avec finally et NonCancellable » est-elle gratuite ?

Oui — le texte complet de « Nettoyage avec finally et NonCancellable » 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 « Nettoyage avec finally et NonCancellable » ?

Libérez les ressources dans les coroutines annulées avec finally et withContext(NonCancellable). 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 3 sur 4.

Combien de temps prend la leçon « Nettoyage avec finally et NonCancellable » ?

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