Co się dzieje z korutyną, gdy wystąpi wyjątek?
sobes.tech AI
Odpowiedź od AI
Gdy w ramach korutyny wystąpi wyjątek, zależność od typu wyjątku (i ustawień dispatcher/kontekstu) decyduje o tym, jak zostanie on obsłużony.
-
Nieobsłużony wyjątek: Jeśli wyjątek nie zostanie przechwycony w ramach korutyny, propaguje się on w górę hierarchii korutyn aż do najbliższego
JoblubCoroutineScope. Zachowanie zależy od typuJob:Job: Domyślnie, gdy w korutynie potomnej wystąpi wyjątek, nadrzędnyJobzostaje anulowany, co powoduje anulowanie wszystkich pozostałych korutyn potomnych. Wyjątek jest propagowany w górę.SupervisorJob: NadrzędnySupervisorJobnie jest anulowany, gdy w korutynie potomnej wystąpi wyjątek. Anulowana jest tylko ta korutyna, w której wystąpił wyjątek. To jest przydatne, gdy chcesz, aby anulowanie jednej zadania potomnego nie wpływało na inne.CoroutineScopegłówny: Jeśli wyjątek dotrze do głównegoCoroutineScope(np.GlobalScopelub scope utworzony za pomocąCoroutineScopebezJob), jest przekazywany do globalnego obsługiwania wyjątkówCoroutineExceptionHandler. Domyślnie, jeśli nie zarejestrowano obsługi, wyjątek jest logowany wSystem.err.
-
Przechwycony wyjątek: Jeśli wyjątek zostanie przechwycony za pomocą bloku
try-catchwewnątrz korutyny, jest obsługiwany lokalnie, a korutyna kontynuuje działanie po blokucatch, jeśli to możliwe. Wyjątek nie jest propagowany w górę. -
Wyjątki związane z anulowaniem (np.
CancellationException): Są to wyjątki specjalne. Używa się ich do mechanizmu anulowania korutyn i są one zazwyczaj ignorowane przez większość domyślnych obsługi wyjątków. Nie powodują one krytycznego błędu nadrzędnegoJob. -
Wyjątki w
async: Korutyna uruchomiona za pomocąasyncumieszcza wyjątek w swoimDeferred. Wyjątek jest propagowany tylko podczas wywołania.await()na tymDeferred. Do tego momentu wyjątek jest "ukryty".
import kotlinx.coroutines.*
fun main() = runBlocking {
val scope = CoroutineScope(SupervisorJob())
scope.launch {
try {
println("Korutyna 1 rozpoczęta")
delay(100)
throw RuntimeException("Coś poszło nie tak w Korutynie 1")
} catch (e: Exception) {
println("Przechwycono wyjątek w Korutynie 1: ${e.message}")
}
}
scope.launch {
println("Korutyna 2 rozpoczęta")
delay(500)
println("Korutyna 2 zakończona")
}
delay(1000) // Czekamy, aby zobaczyć wynik
scope.cancel() // Anulujemy scope
}
W tym przykładzie, wyjątek w Korutynie 1 jest przechwytywany, a Korutyna 2 kontynuuje działanie, ponieważ używany jest SupervisorJob. Gdyby użyto zwykłego Job, wyjątek w Korutynie 1 spowodowałby anulowanie Korutyny 2.