Cosa succede a una coroutine quando si verifica un'eccezione?
sobes.tech AI
Risposta dell'AI
Quando si verifica un'eccezione all'interno di una coroutine, la dipendenza dal tipo di eccezione (e dalle impostazioni del dispatcher/contenuto) determina come verrà gestita.
-
Eccezione non gestita: Se l'eccezione non viene catturata all'interno della coroutine, si propaga verso l'alto nella gerarchia delle coroutines fino al
JoboCoroutineScopepiù vicino. Il comportamento dipende dal tipo diJob:Job: Per impostazione predefinita, quando si verifica un'eccezione in una coroutine figlia, ilJobgenitore viene cancellato, portando alla cancellazione di tutte le altre sue coroutine figlie. L'eccezione si propaga verso l'alto.SupervisorJob: IlSupervisorJobgenitore non viene cancellato quando si verifica un'eccezione in una coroutine figlia. Solo la coroutine in cui si è verificata l'eccezione viene cancellata. Questo è utile quando si desidera che la cancellazione di un task figlio non influenzi gli altri.CoroutineScoperadice: Se l'eccezione raggiunge ilCoroutineScoperadice (ad esempio,GlobalScopeo uno creato conCoroutineScopesenzaJob), viene trasmessa al gestore globale delle eccezioniCoroutineExceptionHandler. Per impostazione predefinita, se non è registrato alcun gestore, l'eccezione viene registrata inSystem.err.
-
Eccezione catturata: Se l'eccezione viene catturata tramite un blocco
try-catchall'interno della coroutine, viene gestita localmente e la coroutine continua l'esecuzione dopo il bloccocatch, se possibile. L'eccezione non si propaga verso l'alto. -
Eccezioni legate alla cancellazione (ad esempio,
CancellationException): Queste eccezioni sono particolari. Sono usate per il meccanismo di cancellazione delle coroutines e di solito vengono ignorate dalla maggior parte dei gestori di eccezioni per impostazione predefinita. Non causano un fallimento fatale delJobgenitore per impostazione predefinita. -
Eccezioni in
async: La coroutine avviata conasyncmette l'eccezione nel suoDeferred. L'eccezione viene propagata solo quando si chiama.await()su questoDeferred. Fino a quel momento, l'eccezione è "nascosta".
import kotlinx.coroutines.*
fun main() = runBlocking {
val scope = CoroutineScope(SupervisorJob())
scope.launch {
try {
println("Coroutine 1 avviata")
delay(100)
throw RuntimeException("Qualcosa è andato storto in Coroutine 1")
} catch (e: Exception) {
println("Eccezione catturata in Coroutine 1: ${e.message}")
}
}
scope.launch {
println("Coroutine 2 avviata")
delay(500)
println("Coroutine 2 terminata")
}
delay(1000) // Attendi per vedere l'output
scope.cancel() // Annulla lo scope
}
In questo esempio, l'eccezione in Coroutine 1 viene catturata e Coroutine 2 continua l'esecuzione perché si utilizza SupervisorJob. Se si usasse invece un Job normale, l'eccezione in Coroutine 1 porterebbe all'annullamento di Coroutine 2.