0Pricing
Kotlin Academy · Lekcja

Propagacja anulowania w hierarchiach korutyn

Poznaj przepływ anulowania w relacjach nadrzędny–podrzędny między korutynami.

Propagacja anulowania w hierarchiach korutyn to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Relacja rodzic–dziecko

Gdy korutyna uruchamia inną korutynę za pomocą launch, dziecko dołącza do obiektu Job rodzica. Anulowanie rodzica anuluje wszystkie dzieci.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val parent = launch {
        launch { delay(1000); println("child 1") }
        launch { delay(1000); println("child 2") }
        delay(1000)
        println("parent")
    }
    delay(50)
    parent.cancel()
    parent.join()
    println("All cancelled")
}

Błąd dziecka anuluje rodzica

Jeśli dziecko zgłosi wyjątek inny niż wyjątek anulowania, anuluje rodzica i całe rodzeństwo — jest to domyślne zachowanie obiektu Job.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        coroutineScope {
            launch {
                delay(50)
                throw RuntimeException("child failed")
            }
            launch {
                delay(1000)
                println("sibling — never prints")
            }
        }
    } catch (e: RuntimeException) {
        println("Caught: ${e.message}")
    }
}

Anulowanie nie propaguje się w górę

Anulowanie dziecka NIE anuluje rodzica. Tylko nieobsłużone wyjątki propagują się w górę. Rodzic może w dowolnym momencie anulować dziecko.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val parent = launch {
        val child = launch {
            delay(1000)
            println("child done")
        }
        delay(50)
        child.cancel()  // cancels child
        child.join()
        println("parent still running")  // parent is fine
    }
    parent.join()
}

coroutineScope a GlobalScope

coroutineScope tworzy zakres podrzędny: anulowanie i błędy propagują się w jego obrębie. GlobalScope tworzy osierocone korutyny bez rodzica — należy unikać go w środowisku produkcyjnym.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        coroutineScope {
            launch { delay(50); throw RuntimeException("error") }
        }
    } catch (e: Exception) {
        println("coroutineScope propagated: ${e.message}")
    }
    // GlobalScope.launch { } would NOT propagate to runBlocking
}

Anulowanie poddrzewa

Każde wywołanie launch lub async zwraca obiekt Job. Anuluj zadanie, aby anulować całe jego poddrzewo, w tym wszystkie zagnieżdżone wywołania launch.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val root = launch {
        launch {
            launch { delay(1000); println("deep") }
            delay(1000)
        }
    }
    delay(50)
    root.cancel()
    root.join()
    println("Whole subtree cancelled")
}

join() po cancel()

Zawsze wywołuj join() po cancel(), aby zaczekać na całkowite zatrzymanie korutyny i jej dzieci przed kontynuowaniem działania.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try { delay(1000) }
        finally { println("cleanup ran") }
    }
    delay(50)
    job.cancel()
    job.join()  // waits for finally to complete
    println("Proceeded after join")
}

cancelAndJoin()

job.cancelAndJoin() to wygodna funkcja, która anuluje zadanie, a następnie wykonuje join; jest równoważna wywołaniom cancel() + join().

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try { delay(1000) }
        finally { println("cleanup") }
    }
    delay(50)
    job.cancelAndJoin()  // cancel + join in one call
    println("Done")
}

Propagacja przez async

W przypadku async wyjątki są przechowywane w obiekcie Deferred i zgłaszane podczas wywołania await(). Jeśli nie zostaną obsłużone, nadal propagują się do rodzica.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        coroutineScope {
            val d = async { throw RuntimeException("async fail") }
            d.await()  // rethrows here
        }
    } catch (e: RuntimeException) {
        println("Caught from async: ${e.message}")
    }
}

Gwarancja programowania współbieżnego ustrukturyzowanego

Programowanie współbieżne ustrukturyzowane gwarantuje, że po zakończeniu zakresu wszystkie jego dzieci również zostały zakończone. Korutyny nie wyciekają — albo kończą działanie, albo zostają anulowane.

import kotlinx.coroutines.*
suspend fun doWork() = coroutineScope {
    launch { delay(100); println("work 1") }
    launch { delay(200); println("work 2") }
    // both children complete before doWork returns
}
fun main() = runBlocking {
    doWork()
    println("All work done")
}

Diagram propagacji anulowania

Hierarchia: anulowanie rodzica → anulowanie wszystkich dzieci. Anulowanie dziecka → tylko jego poddrzewo. Wyjątek dziecka → anulowanie rodzica → anulowanie rodzeństwa.

import kotlinx.coroutines.*
fun main() = runBlocking {
    // Parent
    launch {
        val c1 = launch { delay(1000); println("c1") }  // child 1
        val c2 = launch { delay(1000); println("c2") }  // child 2
        delay(50)
        c1.cancel()  // only c1 cancelled
        c1.join()
        println("c2 still active: ${c2.isActive}")
        c2.cancelAndJoin()
    }.join()
}

Cykl życia CoroutineScope w Androidzie

W systemie Android obiekt viewModelScope zostaje anulowany po usunięciu obiektu ViewModel. Wszystkie uruchomione korutyny są anulowane automatycznie — nie trzeba ręcznie zwalniać zasobów.

import kotlinx.coroutines.*
// Pseudocode:
// class MyViewModel : ViewModel() {
//     fun load() = viewModelScope.launch {
//         val data = repo.fetch() // cancelled if VM cleared
//         _state.value = data
//     }
// }
fun main() = runBlocking { println("viewModelScope cancels on ViewModel.onCleared()") }

Szybkie sprawdzenie

Co dzieje się z korutynami będącymi rodzeństwem, gdy dziecko zgłosi nieobsłużony wyjątek w ramach zwykłego obiektu Job?

Podsumowanie

Anulowanie rodzica kaskadowo anuluje wszystkie dzieci. Błąd dziecka propaguje się do rodzica i rodzeństwa (w przypadku zwykłego obiektu Job). Używaj cancelAndJoin(), aby poprawnie zakończyć działanie. Programowanie współbieżne ustrukturyzowane gwarantuje brak wycieków korutyn.

Często zadawane pytania

Czy lekcja „Propagacja anulowania w hierarchiach korutyn” jest bezpłatna?

Tak — pełny tekst „Propagacja anulowania w hierarchiach korutyn” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Propagacja anulowania w hierarchiach korutyn”?

Poznaj przepływ anulowania w relacjach nadrzędny–podrzędny między korutynami. Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?

Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Propagacja anulowania w hierarchiach korutyn”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?

Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Kooperatywne anulowanie: isActive i ensureActive
  2. withTimeout i withTimeoutOrNull
  3. Sprzątanie za pomocą finally i NonCancellable
  4. Propagacja anulowania w hierarchiach korutyn
← Powrót do Kotlin Academy