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
- Cancelamento cooperativo: isActive e ensureActive
- withTimeout e withTimeoutOrNull
- Limpeza com finally e NonCancellable
- Propagação de cancelamento em hierarquias de corrotinas