0Pricing
Kotlin Academy · Aula

Propagação de cancelamento em hierarquias de corrotinas

Entenda como o cancelamento percorre as relações entre corrotinas pai e filhas.

Propagação de cancelamento em hierarquias de corrotinas é uma aula grátis de Kotlin Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Kotlin Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Kotlin Academy inclui 4 aulas no total.

Relação entre pai e filho

Quando uma corrotina inicia outra com launch, a filha é vinculada ao Job do pai. Cancelar o pai cancela todas as filhas.

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")
}

Falha do filho cancela o pai

Se uma filha lançar uma exceção que não seja de cancelamento, ela cancelará o pai e todas as irmãs — esse é o comportamento padrão de 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}")
    }
}

O cancelamento não se propaga para cima

O cancelamento de uma filha não cancela o pai (NOT). Apenas exceções não tratadas fazem isso. Um pai pode cancelar uma filha a qualquer momento.

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 em comparação com GlobalScope

coroutineScope cria um escopo filho: o cancelamento e os erros se propagam. GlobalScope cria corrotinas órfãs sem um pai — evite-o em produção.

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
}

Cancelando uma subárvore

Cada launch ou async retorna um Job. Cancele um trabalho para cancelar toda a sua subárvore, incluindo quaisquer inicializações aninhadas.

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() após cancel()

Sempre chame join() depois de cancel() para aguardar que a corrotina e suas filhas parem completamente antes de continuar.

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() é uma conveniência que cancela e depois aguarda a conclusão, equivalente a 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")
}

Propagação por meio de operações assíncronas

Com async, as exceções são armazenadas em Deferred e lançadas quando você chama await(). Elas ainda se propagam para o pai se não forem tratadas.

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}")
    }
}

Garantia da concorrência estruturada

A concorrência estruturada garante que, quando um escopo termina, todas as suas filhas já terminaram. Não há vazamentos de corrotinas — elas são concluídas ou canceladas.

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")
}

Diagrama da propagação do cancelamento

A hierarquia: cancelamento do pai → todas as filhas canceladas. Cancelamento da filha → somente essa subárvore. Exceção da filha → pai cancelado → irmãs canceladas.

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()
}

Ciclo de vida de CoroutineScope no Android

No Android, viewModelScope é cancelado quando o ViewModel é limpo. Todas as corrotinas iniciadas são canceladas automaticamente — não é necessária nenhuma limpeza manual.

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()") }

Verificação rápida

O que acontece com as corrotinas irmãs quando uma filha lança uma exceção não tratada sob um Job comum?

Recapitulação

O cancelamento do pai se propaga em cascata para todas as filhas. A falha de uma filha se propaga para o pai e para as irmãs (com um Job comum). Use cancelAndJoin() para um encerramento limpo. A concorrência estruturada garante que não haja vazamentos de corrotinas.

Perguntas Frequentes

A aula “Propagação de cancelamento em hierarquias de corrotinas” é grátis?

Sim — o texto completo de “Propagação de cancelamento em hierarquias de corrotinas” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Kotlin Academy, atualize para CoddyKit PRO. O curso de Kotlin Academy inclui 4 aulas no total.

O que vou aprender em “Propagação de cancelamento em hierarquias de corrotinas”?

Entenda como o cancelamento percorre as relações entre corrotinas pai e filhas. Você pratica Kotlin Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Kotlin Academy?

Nenhuma experiência prévia é necessária. Kotlin Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.

Quanto tempo leva a aula “Propagação de cancelamento em hierarquias de corrotinas”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Kotlin Academy?

Sim. Cada aula de Kotlin Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Cancelamento cooperativo: isActive e ensureActive
  2. withTimeout e withTimeoutOrNull
  3. Limpeza com finally e NonCancellable
  4. Propagação de cancelamento em hierarquias de corrotinas
← Voltar para Kotlin Academy