Sobes.tech
Middle

Kas nutinka korutinai, kai įvyksta išimtis?

sobes.tech AI

Atsakymas iš AI

Kai korutinoje įvyksta išimtis, jos tvarkymas priklauso nuo išimties tipo (ir dispečerio/konteksto nustatymų).

  • Nevaldomas išimtis: Jei išimtis nebuvo pagauta korutinoje, ji kyla aukštyn per korutinų hierarchiją iki artimiausio Job (arba CoroutineScope). Elgsena priklauso nuo Job tipo:

    • Job: Pagal numatytuosius nustatymus, jei įvyksta išimtis vaikų korutinoje, tėvinis Job atšaukiamas, kas sukelia visų kitų jo vaikų korutinų atšaukimą. Išimtis perduodama aukštyn.
    • SupervisorJob: SupervisorJob nebus atšauktas, jei įvyksta išimtis vaikų korutinoje. Tik ta korutina, kurioje įvyko išimtis, bus atšaukta. Tai naudinga, kai norima, kad vieno vaiko užduoties atšaukimas neturėtų įtakos kitoms.
    • Pagrindinis CoroutineScope: Jei išimtis pasiekia pagrindinį CoroutineScope (pvz., GlobalScope arba CoroutineScope sukurtą be Job), ji perduodama į globalų CoroutineExceptionHandler. Pagal numatytuosius nustatymus, jei nėra registruoto tvarkytojo, išimtis įrašoma į System.err.
  • Pagauta išimtis: Jei išimtis buvo pagauta naudojant try-catch bloką korutinoje, ji apdorojama vietoje, ir korutina tęsia veiklą po catch bloko, jei tai įmanoma. Išimtis nėra perduodama aukštyn.

  • Išimtys, susijusios su atšaukimu (pvz., CancellationException): Šios išimtys yra ypatingos. Jos naudojamos korutinų atšaukimo mechanizmui ir dažniausiai ignoruojamos daugumos išimtis apdorotojų pagal numatytuosius nustatymus. Jos nesukelia lemiamos klaidos tėvinio Job atžvilgiu.

  • async-o išimtys: Korutina, paleista per async, įdeda išimtį į savo Deferred. Išimtis perduodama tik iškvietus .await() ant šio Deferred. Iki to momento išimtis yra "paslėpta".

import kotlinx.coroutines.*

fun main() = runBlocking {
    val scope = CoroutineScope(SupervisorJob())

    scope.launch {
        try {
            println("Korutina 1 pradėta")
            delay(100)
            throw RuntimeException("Kažkas nepavyko Korutinoje 1")
        } catch (e: Exception) {
            println("Pagauta išimtis Korutinoje 1: ${e.message}")
        }
    }

    scope.launch {
        println("Korutina 2 pradėta")
        delay(500)
        println("Korutina 2 baigta")
    }

    delay(1000) // Laukiame rezultatų
    scope.cancel() // Atšaukiame scope
}

Šiame pavyzdyje, išimtis Korutinoje 1 yra pagauta, ir Korutina 2 tęsia darbą, nes naudojamas SupervisorJob. Jei būtų naudojamas įprastas Job, išimtis Korutinoje 1 sukeltų Korutinos 2 atšaukimą.