Mi történik a coroutine-nal, amikor kivétel lép fel?
sobes.tech MI
Válasz az MI-től
Amikor egy kivétel fordul elő egy coroutine belsejében, a kivétel típusától (és a dispatcher/kontekstus beállításaitól) függően dől el, hogyan kezeljük.
-
Kezeletlen kivétel: Ha a kivételt nem fogják el egy coroutine belsejében, akkor felfelé terjed a coroutine hierarchiában a legközelebbi
JobvagyCoroutineScope-ig. A viselkedés aJobtípusától függ:Job: Alapértelmezés szerint, ha egy gyermek coroutine-ban kivétel történik, az szülőJob-ja törlődik, ami a többi gyermek coroutine törléséhez vezet. A kivétel felfelé terjed.SupervisorJob: A szülőSupervisorJobnem törlődik, ha kivétel történik egy gyermek coroutine-ban. Csak az a coroutine törlődik, ahol a kivétel történt. Ez akkor hasznos, ha azt akarod, hogy egy gyermek feladat törlése ne befolyásolja a többit.CoroutineScopegyökér: Ha a kivétel eléri a gyökérCoroutineScope-t (például,GlobalScopevagy egyCoroutineScopenélküli scope), akkor átadódik a globálisCoroutineExceptionHandler-nek. Alapértelmezés szerint, ha nincs regisztrált kezelő, a kivétel aSystem.err-ben kerül naplózásra.
-
Elkapott kivétel: Ha a kivételt
try-catchblokk segítségével fogják el a coroutine belsejében, akkor helyben kezelődik, és a coroutine folytatódik acatchblokk után, ha ez lehetséges. A kivétel nem terjed felfelé. -
A kivételek, amelyek a törléssel kapcsolatosak (például
CancellationException): Ezek különlegesek. A coroutine törlési mechanizmusához használják, és általában figyelmen kívül hagyják a legtöbb alapértelmezett kivételkezelő által. Alapértelmezés szerint nem okoznak fatális hibát a szülőJob-ban. -
async-ben lévő kivételek: Azasync-szal indított coroutine a kivételt a sajátDeferred-jébe helyezi. A kivétel csak akkor terjed, amikor.await()-ot hívnak erre aDeferred-re. Eddig a kivétel "el van rejtve".
import kotlinx.coroutines.*
fun main() = runBlocking {
val scope = CoroutineScope(SupervisorJob())
scope.launch {
try {
println("Coroutine 1 indult")
delay(100)
throw RuntimeException("Valami rosszul sült el a Coroutine 1-ben")
} catch (e: Exception) {
println("Elkapott kivétel a Coroutine 1-ben: ${e.message}")
}
}
scope.launch {
println("Coroutine 2 indult")
delay(500)
println("Coroutine 2 befejeződött")
}
delay(1000) // Várunk, hogy lássuk az eredményt
scope.cancel() // Scope leállítása
}
Ebben a példában a Coroutine 1-ben keletkezett kivétel el van kapva, és a Coroutine 2 folytatódik, mert SupervisorJob van használatban. Ha egy normál Job-ot használnánk helyette, a Coroutine 1-ben keletkezett kivétel a Coroutine 2 törléséhez vezetne.