Kotlin Academy · Pelajaran

Pembersihan dengan finally dan NonCancellable

Lepaskan sumber dalam coroutine yang dibatalkan menggunakan finally dan withContext(NonCancellable).

Pelajaran 3 daripada 413 langkah

Pembersihan dengan finally dan NonCancellable ialah pelajaran Kotlin Academy percuma di CoddyKit. Ini ialah pelajaran 3 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Kotlin Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Kotlin Academy merangkumi sejumlah 4 pelajaran.

Pembatalan dan Blok Akhir

Apabila korutin dibatalkan, titik penangguhan melemparkan CancellationException. Kod dalam blok finally sentiasa dijalankan — tetapi blok finally itu sendiri berjalan dalam konteks korutin yang telah dibatalkan.

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

Masalah: Penangguhan dalam Blok Akhir

Jika anda cuba memanggil delay atau melakukan penangguhan lain dalam blok finally bagi korutin yang telah dibatalkan, panggilan itu akan melemparkan pengecualian serta-merta kerana konteks tersebut sudah dibatalkan.

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)

Balut panggilan penangguhan dalam blok finally dengan withContext(NonCancellable) supaya panggilan tersebut berjalan dalam konteks yang tidak boleh dibatalkan walaupun induk telah dibatalkan.

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

Bila Perlu Menggunakan NonCancellable

Gunakan NonCancellable untuk: menutup sambungan pangkalan data, mengosongkan catatan log, menghantar peristiwa analitik atau melakukan sebarang pembersihan tak segerak yang mesti selesai tanpa mengira pembatalan.

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 Bukan Skop

NonCancellable ialah Job yang boleh anda hantarkan kepada withContext. Jangan gunakannya terus sebagai skop korutin — gunakannya hanya dalam pembersihan blok 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() }
}

Pembersihan Berbilang Sumber

Rangkaikan berbilang operasi pembersihan dalam satu blok 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() }
}

Corak Cuba/Tangkap/Akhir

Gabungkan percubaan dan tangkapan untuk ralat perniagaan dengan blok akhir untuk pembersihan — ini ialah corak berstruktur 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()
}

Urutan Pembersihan

Blok akhir dijalankan dalam susunan songsang daripada susunan bersarang. Blok cuba-akhir luaran dijalankan selepas blok dalaman, sama seperti dalam kod Java/Kotlin biasa.

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

guna() untuk Sumber AutoCloseable

Bagi sumber AutoCloseable, gunakan sambungan Kotlin use { } yang memanggil close() secara automatik, walaupun berlaku pengecualian atau pembatalan.

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

Mencatat Sebab Pembatalan

Dapatkan mesej pembatalan daripada CancellationException dalam catch atau finally untuk mencatat sebab korutin berhenti.

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

Pembersihan CoroutineScope dengan invokeOnCompletion

Job.invokeOnCompletion mendaftarkan panggilan balik yang dijalankan apabila tugas selesai atas apa-apa sebab — alternatif kepada finally untuk pembersihan pada peringkat induk.

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

Semakan Pantas

Apakah tujuan withContext(NonCancellable) dalam blok finally?

Rumusan

finally sentiasa dijalankan apabila berlaku pembatalan. Balut panggilan penangguhan dalam finally dengan withContext(NonCancellable) supaya panggilan tersebut selesai walaupun berlaku pembatalan. Gunakan use { } untuk sumber AutoCloseable.

Percuma untuk bermula

Pelajari Kotlin dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
51
Pelajaran
203

Soalan Lazim

Adakah pelajaran “Pembersihan dengan finally dan NonCancellable” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Kotlin Academy, termasuk “Pembersihan dengan finally dan NonCancellable”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Kotlin Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Pembersihan dengan finally dan NonCancellable”?

Lepaskan sumber dalam coroutine yang dibatalkan menggunakan finally dan withContext(NonCancellable). Anda berlatih Kotlin Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Kotlin Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Kotlin Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 3 daripada 4.

Berapa lamakah pelajaran “Pembersihan dengan finally dan NonCancellable” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Kotlin Academy ini?

Ya. Setiap pelajaran Kotlin Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Pembatalan Koperatif: isActive dan ensureActive
  2. withTimeout dan withTimeoutOrNull
  3. Pembersihan dengan finally dan NonCancellable
  4. Penyebaran Pembatalan dalam Hierarki Coroutine
← Kembali ke Kotlin Academy