0Pricing
Kotlin Academy · Lektion

Aufräumen mit finally und NonCancellable

Geben Sie Ressourcen in abgebrochenen Coroutines mit finally und withContext(NonCancellable) frei.

Aufräumen mit finally und NonCancellable ist eine kostenlose Kotlin Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Kotlin Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.

Abbruch und finally

Wenn eine Coroutine abgebrochen wird, lösen Suspend-Punkte CancellationException aus. Code in finally-Blöcken wird immer ausgeführt – finally selbst läuft jedoch in einem bereits abgebrochenen Coroutine-Kontext.

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

Problem: Suspendieren in finally

Wenn Sie in finally einer abgebrochenen Coroutine delay oder eine andere Suspendierung ausführen, wird sofort eine Ausnahme ausgelöst, weil der Kontext bereits abgebrochen ist.

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)

Verpacken Sie Suspendierungsaufrufe in finally mit withContext(NonCancellable), damit sie auch nach dem Abbruch des übergeordneten Kontexts in einem nicht abbrechbaren Kontext ausgeführt werden.

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

Wann NonCancellable verwendet wird

Verwenden Sie NonCancellable zum Schließen von Datenbankverbindungen, zum Flushen von Logs, zum Senden von Analyseereignissen oder für jede asynchrone Bereinigung, die unabhängig von einem Abbruch abgeschlossen werden muss.

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 ist kein Scope

NonCancellable ist ein Job, den Sie an withContext übergeben können. Verwenden Sie ihn nicht direkt als Coroutine-Scope, sondern nur zur Bereinigung in 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() }
}

Bereinigung mehrerer Ressourcen

Reihen Sie mehrere Bereinigungsoperationen innerhalb eines einzigen Blocks von withContext(NonCancellable) aneinander.

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

Das try/catch/finally-Muster

Kombinieren Sie try-catch für fachliche Fehler mit finally zur Bereinigung – dies ist das übliche strukturierte Muster.

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

Reihenfolge der Bereinigung

Finally-Blöcke werden in umgekehrter Verschachtelungsreihenfolge ausgeführt. Der äußere try-finally-Block wird nach den inneren ausgeführt, genau wie bei normalem Java- oder Kotlin-Code.

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

use() für AutoCloseable-Ressourcen

Verwenden Sie für AutoCloseable-Ressourcen die Kotlin-Erweiterung use { }. Sie ruft close() automatisch auf, auch bei Ausnahmen oder einem Abbruch.

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

Grund des Abbruchs protokollieren

Lesen Sie die Abbruchnachricht von CancellationException in catch oder finally aus, um zu protokollieren, warum eine Coroutine beendet wurde.

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

Bereinigung eines CoroutineScope mit invokeOnCompletion

Job.invokeOnCompletion registriert einen Callback, der ausgeführt wird, wenn der Job aus irgendeinem Grund beendet wird – eine Alternative zu finally für die Bereinigung auf Ebene des übergeordneten Jobs.

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

Kurze Überprüfung

Welchen Zweck hat withContext(NonCancellable) in einem finally-Block?

Zusammenfassung

finally wird bei einem Abbruch immer ausgeführt. Verpacken Sie Suspendierungsaufrufe innerhalb von finally mit withContext(NonCancellable), damit sie trotz des Abbruchs abgeschlossen werden. Verwenden Sie use { } für AutoCloseable-Ressourcen.

Häufig gestellte Fragen

Ist die Lektion „Aufräumen mit finally und NonCancellable“ kostenlos?

Ja — der vollständige Text von „Aufräumen mit finally und NonCancellable“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Kotlin Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Aufräumen mit finally und NonCancellable“?

Geben Sie Ressourcen in abgebrochenen Coroutines mit finally und withContext(NonCancellable) frei. Du übst Kotlin Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Kotlin Academy zu starten?

Keine Vorkenntnisse erforderlich. Kotlin Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.

Wie lange dauert die Lektion „Aufräumen mit finally und NonCancellable“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Kotlin Academy-Lektion Code schreiben und ausführen?

Ja. Jede Kotlin Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Kooperative Abbruchbehandlung: isActive und ensureActive
  2. withTimeout und withTimeoutOrNull
  3. Aufräumen mit finally und NonCancellable
  4. Abbruchweitergabe in Coroutine-Hierarchien
← Zurück zu Kotlin Academy