Sobes.tech
Middle

Kas notiek ar korutīnu, kad rodas izņēmums?

sobes.tech AI

Atbilde no AI

Kad korutīnā rodas izņēmums, tā apstrādes veids ir atkarīgs no izņēmuma veida (un dispatcher/konteksta iestatījumiem).

  • Nekontrolēts izņēmums: Ja izņēmums nav noķerts korutīnā, tas tiek propagēts augšup pa korutīnu hierarhiju līdz tuvākajam Job (vai CoroutineScope). Uzvedība ir atkarīga no Job veida:

    • Job: Pēc noklusējuma, ja notiek izņēmums bērnu korutīnā, vecāka Job tiek atcelta, kas noved pie visu citu tās bērnu korutīnu atcelšanas. Izņēmums tiek pārsūtīts augšup.
    • SupervisorJob: SupervisorJob netiek atcelts, ja notiek izņēmums bērnu korutīnā. Tikai tā korutīna, kurā notika izņēmums, tiks atcelta. Tas ir noderīgi, ja nepieciešams, lai viena bērna uzdevuma atcelšana neietekmētu citas.
    • CoroutineScope galvenais: Ja izņēmums sasniedz CoroutineScope (piemēram, GlobalScope vai CoroutineScope izveidots bez Job), tas tiek nodots globālajam izņēmumu apstrādātājam CoroutineExceptionHandler. Pēc noklusējuma, ja nav reģistrēts apstrādātājs, izņēmums tiek reģistrēts System.err.
  • Noķerts izņēmums: Ja izņēmums tiek noķerts ar try-catch bloku korutīnā, tas tiek apstrādāts lokāli, un korutīna turpina darbu pēc catch bloka, ja tas ir iespējams. Izņēmums netiek pārsūtīts augšup.

  • Saistītie ar atcelšanu izņēmumi (piemēram, CancellationException): Šie izņēmumi ir īpaši. Tie tiek izmantoti korutīnu atcelšanas mehānisma nodrošināšanai un parasti tiek ignorēti lielākajā daļā izņēmumu apstrādātāju pēc noklusējuma. Tie nerada fatālu kļūmi vecā Job gadījumā.

  • async-a izņēmumi: Korutīna, kas sākta ar async, ievieto izņēmumu savā Deferred. Izņēmums tiek pārsūtīts tikai, izsaucot .await() uz šī Deferred. Līdz tam izņēmums ir "slēpts".

import kotlinx.coroutines.*

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

    scope.launch {
        try {
            println("Korutīna 1 sākās")
            delay(100)
            throw RuntimeException("Kas notika Korutīnā 1")
        } catch (e: Exception) {
            println("Noķerts izņēmums Korutīnā 1: ${e.message}")
        }
    }

    scope.launch {
        println("Korutīna 2 sākās")
        delay(500)
        println("Korutīna 2 pabeigta")
    }

    delay(1000) // Gaidām rezultātu
    scope.cancel() // Atceļam scope
}

Šajā piemērā, izņēmums Korutīnā 1 ir noķerts, un Korutīna 2 turpina darbu, jo ir izmantots SupervisorJob. Ja būtu izmantots parasts Job, tad izņēmums Korutīnā 1 izraisītu Korutinas 2 atcelšanu.