Sobes.tech
Middle

Wat gebeurt er met een coroutine wanneer er een uitzondering optreedt?

sobes.tech AI

Antwoord van AI

Wanneer er een uitzondering optreedt binnen een coroutine, bepaalt de afhankelijkheid van het type uitzondering (en de dispatcher/context-instellingen) hoe deze wordt afgehandeld.

  • Ongecontroleerde uitzondering: Als de uitzondering niet binnen de coroutine wordt opgevangen, wordt deze omhoog in de hiërarchie van coroutines doorgegeven tot aan de dichtstbijzijnde Job of CoroutineScope. Het gedrag hangt af van het type Job:

    • Job: Standaard wordt, wanneer een uitzondering optreedt in een kind-coroutine, de bovenliggende Job geannuleerd, wat leidt tot het annuleren van alle andere onderliggende coroutines. De uitzondering wordt omhoog doorgegeven.
    • SupervisorJob: De bovenliggende SupervisorJob wordt niet geannuleerd wanneer een uitzondering optreedt in een kind-coroutine. Alleen de coroutine waarin de uitzondering plaatsvond, wordt geannuleerd. Dit is handig wanneer je wilt dat het annuleren van een kind-taak de anderen niet beïnvloedt.
    • CoroutineScope root: Als de uitzondering de CoroutineScope root bereikt (bijvoorbeeld GlobalScope of een scope gemaakt met CoroutineScope zonder Job), wordt deze doorgestuurd naar de globale CoroutineExceptionHandler. Standaard wordt, als er geen handler is geregistreerd, de uitzondering gelogd in System.err.
  • Opgevangen uitzondering: Als de uitzondering wordt opgevangen met een try-catch-blok binnen de coroutine, wordt deze lokaal afgehandeld en gaat de coroutine verder na het catch-blok, indien mogelijk. De uitzondering wordt niet omhoog doorgegeven.

  • Uitzonderingen gerelateerd aan annulering (bijvoorbeeld CancellationException): Deze uitzonderingen zijn speciaal. Ze worden gebruikt voor het annuleringmechanisme van coroutines en worden meestal genegeerd door de meeste standaard exception handlers. Ze veroorzaken niet standaard een fatale fout in de bovenliggende Job.

  • Uitzonderingen in async: Een met async gestartde coroutine plaatst de uitzondering in haar Deferred. De uitzondering wordt alleen doorgegeven bij het aanroepen van .await() op dat Deferred. Tot die tijd is de uitzondering "verborgen".

import kotlinx.coroutines.*

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

    scope.launch {
        try {
            println("Coroutine 1 gestart")
            delay(100)
            throw RuntimeException("Er is iets misgegaan in Coroutine 1")
        } catch (e: Exception) {
            println("Opgevangen uitzondering in Coroutine 1: ${e.message}")
        }
    }

    scope.launch {
        println("Coroutine 2 gestart")
        delay(500)
        println("Coroutine 2 voltooid")
    }

    delay(1000) // Wacht om de output te zien
    scope.cancel() // Annuleer scope
}

In dit voorbeeld wordt de uitzondering in Coroutine 1 opgevangen en gaat Coroutine 2 door met uitvoeren omdat SupervisorJob wordt gebruikt. Als in plaats daarvan een gewone Job zou worden gebruikt, zou de uitzondering in Coroutine 1 leiden tot het annuleren van Coroutine 2.