Siivous finally- ja NonCancellable-rakenteilla
Vapauttakaa peruutettujen korutiinien resurssit finally-rakenteella ja withContext(NonCancellable)-kutsulla.
Siivous finally- ja NonCancellable-rakenteilla on ilmainen Kotlin Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Kotlin Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Kotlin Academy-kurssilla on yhteensä 4 oppituntia.
Peruutus ja finally
Kun korutiini peruutetaan, suspensiopisteet heittävät CancellationException-poikkeuksen. finally-lohkojen koodi suoritetaan aina — mutta finally suoritetaan itse peruutetussa korutiinikontekstissa.
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
try {
delay(1000)
} finally {
println("finally: cleaning up")
}
}
delay(50)
job.cancel()
job.join()
}Ongelma: suspensio finally-lohkossa
Jos yritätte kutsua delay-funktiota tai tehdä muun suspendoivan kutsun peruutetun korutiinin finally-lohkossa, kutsu heittää poikkeuksen heti, koska konteksti on jo peruutettu.
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)
Ympäröikää finally-lohkon suspendoivat kutsut withContext(NonCancellable)-kutsulla, jotta ne suoritetaan peruutuksesta huolimatta peruuttamattomassa kontekstissa.
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()
}Milloin NonCancellableia käytetään
Käyttäkää NonCancellable-arvoa tietokantayhteyksien sulkemiseen, lokien tyhjentämiseen, analytiikkatapahtumien lähettämiseen tai muuhun asynkroniseen siivoukseen, joka on saatettava loppuun peruutuksesta riippumatta.
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 ei ole scope
NonCancellable on Job, jonka voitte välittää withContext-funktiolle. Älkää käyttäkö sitä suoraan korutiiniskoopina — käyttäkää sitä vain finally-lohkon siivouksessa.
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() }
}Useiden resurssien siivous
Ketjuttakaa useat siivoustoiminnot yhden withContext(NonCancellable)-lohkon sisällä.
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() }
}try/catch/finally-malli
Yhdistäkää try-catch liiketoimintavirheiden käsittelyyn ja finally resurssien siivoukseen — tämä on vakiintunut rakenteinen malli.
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()
}Siivouksen suoritusjärjestys
Finally-lohkot suoritetaan sisäkkäisyyden käänteisessä järjestyksessä. Ulompi try-finally suoritetaan sisempien jälkeen aivan kuten tavallisessa Java/Kotlin-koodissa.
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() AutoCloseable-resursseille
AutoCloseable-resursseja käsitellessänne käyttäkää Kotlinin use { }-laajennusta, joka kutsuu close()-funktiota automaattisesti myös poikkeusten tai peruutuksen yhteydessä.
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)
}Peruutuksen syyn kirjaaminen
Voitte hakea peruutusviestin CancellationException-poikkeuksesta catch- tai finally-lohkossa ja kirjata lokiin syyn, jonka vuoksi korutiini pysähtyi.
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()
}CoroutineScopen siivous invokeOnCompletion-funktiolla
Job.invokeOnCompletion rekisteröi takaisinsoiton, joka suoritetaan, kun työ päättyy mistä tahansa syystä — se on vaihtoehto finally-lohkolla tehtävälle ylätason siivoukselle.
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()
}Pikatarkistus
Mikä on withContext(NonCancellable)-kutsun tarkoitus finally-lohkossa?
Yhteenveto
finally suoritetaan aina peruutuksen yhteydessä. Ympäröikää finally-lohkon sisällä olevat suspendoivat kutsut withContext(NonCancellable)-kutsulla, jotta ne valmistuvat peruutuksesta huolimatta. Käyttäkää use { }-rakennetta AutoCloseable-resursseille.
Opi Kotlin tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 51
- Oppitunnit
- 203
Usein kysytyt kysymykset
Onko oppitunti ”Siivous finally- ja NonCancellable-rakenteilla” ilmainen?
Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Kotlin Academy-oppimispolun 3 oppituntia, myös oppitunnin “Siivous finally- ja NonCancellable-rakenteilla”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Kotlin Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Siivous finally- ja NonCancellable-rakenteilla”?
Vapauttakaa peruutettujen korutiinien resurssit finally-rakenteella ja withContext(NonCancellable)-kutsulla. Harjoittelet Kotlin Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Kotlin Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Kotlin Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.
Kuinka kauan ”Siivous finally- ja NonCancellable-rakenteilla”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Kotlin Academy-oppitunnilla?
Kyllä. Jokainen Kotlin Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Yhteistoiminnallinen peruutus: isActive ja ensureActive
- withTimeout ja withTimeoutOrNull
- Siivous finally- ja NonCancellable-rakenteilla
- Peruutuksen eteneminen korutiinihierarkioissa