Kotlin Academy · Aula

Limpeza com finally e NonCancellable

Libere recursos em corrotinas canceladas usando finally e withContext(NonCancellable).

Aula 3 de 413 etapas

Limpeza com finally e NonCancellable é uma aula grátis de Kotlin Academy no CoddyKit. Esta é a aula 3 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.

Cancelamento e finalização

Quando uma corrotina é cancelada, os pontos de suspensão lançam CancellationException. O código nos blocos finally sempre é executado — mas o próprio finally é executado em um contexto de corrotina já cancelado.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try {
            delay(1000)
        } finally {
            println("finally: cleaning up")
        }
    }
    delay(50)
    job.cancel()
    job.join()
}

Problema: suspensão na finalização

Se você tentar usar delay ou realizar outra suspensão dentro de finally em uma corrotina cancelada, a operação lançará uma exceção imediatamente porque o contexto já está cancelado.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try {
            delay(1000)
        } finally {
            // delay(100) // throws CancellationException here!
            println("Sync cleanup OK; async cleanup needs NonCancellable")
        }
    }
    delay(50); job.cancel(); job.join()
}

withContext(NonCancellable)

Envolva as chamadas de suspensão em finally com withContext(NonCancellable) para executá-las em um contexto não cancelável mesmo depois que o pai for cancelado.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try {
            delay(1000)
        } finally {
            withContext(NonCancellable) {
                delay(100)  // OK: runs despite cancellation
                println("Async cleanup complete")
            }
        }
    }
    delay(50); job.cancel(); job.join()
}

Quando usar NonCancellable

Use NonCancellable para fechar conexões com bancos de dados, descarregar registros, enviar eventos de análise ou realizar qualquer limpeza assíncrona que precise ser concluída independentemente do cancelamento.

import kotlinx.coroutines.*
suspend fun closeConnection() {
    println("Closing DB connection...")
    delay(50) // simulate async close
    println("Connection closed")
}
fun main() = runBlocking {
    val job = launch {
        try { delay(1000) }
        finally { withContext(NonCancellable) { closeConnection() } }
    }
    delay(50); job.cancel(); job.join()
}

NonCancellable não é um escopo

NonCancellable é um Job que você pode passar para withContext. Não o use diretamente como um escopo de corrotina — use-o apenas na limpeza em finally.

import kotlinx.coroutines.*
fun main() = runBlocking {
    // WRONG usage:
    // launch(NonCancellable) { ... } // launches a coroutine that cannot be cancelled
    // RIGHT usage:
    launch {
        try { delay(500) }
        finally {
            withContext(NonCancellable) {
                println("Safe cleanup")
            }
        }
    }.also { delay(50); it.cancel(); it.join() }
}

Limpeza de vários recursos

Encadeie várias operações de limpeza dentro de um único bloco withContext(NonCancellable).

import kotlinx.coroutines.*
fun main() = runBlocking {
    launch {
        try {
            delay(1000)
        } finally {
            withContext(NonCancellable) {
                delay(20); println("Step 1: flush cache")
                delay(20); println("Step 2: close socket")
                delay(20); println("Step 3: log audit")
            }
        }
    }.also { delay(50); it.cancel(); it.join() }
}

Padrão de tentativa, captura e finalização

Combine a captura de erros de negócio com a finalização para a limpeza — esse é o padrão estruturado usual.

import kotlinx.coroutines.*
fun main() = runBlocking {
    launch {
        try {
            delay(100)
            throw RuntimeException("business error")
        } catch (e: RuntimeException) {
            println("Handling: ${e.message}")
        } finally {
            withContext(NonCancellable) {
                println("Always cleanup")
            }
        }
    }.join()
}

Ordem da limpeza

Os blocos de finalização são executados na ordem inversa do aninhamento. O bloco externo de tentativa e finalização é executado depois dos internos, assim como no código comum de Java e Kotlin.

import kotlinx.coroutines.*
fun main() = runBlocking {
    launch {
        try {
            try {
                delay(1000)
            } finally { println("Inner cleanup") }
        } finally { println("Outer cleanup") }
    }.also { delay(50); it.cancel(); it.join() }
}

Uso de recursos AutoCloseable

Para recursos AutoCloseable, use a extensão use { } do Kotlin, que chama close() automaticamente, mesmo em caso de exceções ou cancelamento.

import kotlinx.coroutines.*
class Connection : AutoCloseable {
    init { println("Opened") }
    override fun close() { println("Closed") }
    suspend fun query(): String { delay(50); return "result" }
}
fun main() = runBlocking {
    val result = Connection().use { it.query() }
    println(result)
}

Registrando o motivo do cancelamento

Recupere a mensagem de cancelamento de CancellationException em catch ou finally para registrar por que uma corrotina foi interrompida.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try {
            delay(1000)
        } catch (e: CancellationException) {
            println("Cancelled: ${e.message}")
            throw e
        }
    }
    delay(50)
    job.cancel("user navigated away")
    job.join()
}

Limpeza de CoroutineScope com invokeOnCompletion

Job.invokeOnCompletion registra uma chamada de retorno executada quando o trabalho termina por qualquer motivo — uma alternativa a finally para a limpeza no nível do pai.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        delay(1000)
    }
    job.invokeOnCompletion { cause ->
        if (cause != null) println("Ended with: ${cause::class.simpleName}")
        else println("Completed normally")
    }
    delay(50)
    job.cancel()
    job.join()
}

Verificação rápida

Qual é a finalidade de withContext(NonCancellable) em um bloco finally?

Recapitulação

finally sempre é executado durante o cancelamento. Envolva as chamadas de suspensão dentro de finally com withContext(NonCancellable) para que sejam concluídas apesar do cancelamento. Use use { } para recursos AutoCloseable.

Grátis para começar

Aprenda Kotlin com um tutor de IA — grátis

Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.

Cursos
51
Aulas
203

Perguntas Frequentes

A aula “Limpeza com finally e NonCancellable” é grátis?

Sim — o texto completo de “Limpeza com finally e NonCancellable” é 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 “Limpeza com finally e NonCancellable”?

Libere recursos em corrotinas canceladas usando finally e withContext(NonCancellable). 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 3 de 4.

Quanto tempo leva a aula “Limpeza com finally e NonCancellable”?

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