finally 사용해 리소스 닫기
취소 가능한 일시 중단 함수는 취소 시에 CancellationException을 throw하며, 이는 일반적인 방식으로 처리할 수 있다. 예를 들어 try { ... } 와 finally { ... } 구문이나, Kotlin의 use 함수는 Coroutine이 취소될 때 정상적으로 종료 작업을 수행한다.
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
try {
repeat(1000) { i ->
println("job: I'm sleeping $i ...")
delay(500L)
}
} finally {
println("job: I'm running finally")
}
}
delay(1300L) // delay a bit
println("main: I'm tired of waiting!")
job.cancelAndJoin() // cancels the job and waits for its completion
println("main: Now I can quit.")
}
📌 전체 코드는 이곳에서 확인할 수 있습니다.
join과 cancelAndJoin 모두 종료 작업이 완료될 때까지 기다린다. 따라서 위의 예시는 다음의 결과를 생성한다.
job: I'm sleeping 0 ...
job: I'm sleeping 1 ...
job: I'm sleeping 2 ...
main: I'm tired of waiting!
job: I'm running finally
main: Now I can quit.
이 글은 Coroutines 공식 문서를 번역한 글입니다.
원문 : Cancellation and timeouts - Closing resources with finally
원문 최종 수정 : 2022년 6월 27일
실행 취소가 불가능한 블록 실행하기
이전 예제에서 finally 블록 내부에서 일시 중단 함수를 사용하려고 하면 이 코드를 실행 중인 코루틴이 취소되기 때문에 CancellationException이 발생한다*1. 잘 작동하는 리소스를 닫는 작업들(파일 닫기, Job 취소하기 또는 모든 종류의 통신 채널을 닫기)은 보통 Blocking을 하지 않는 작업들이며, 어떠한 일시 중단 함수들도 포함하고 있지 않기 때문에 보통 문제가 되지 않는다. 하지만, 드물게 취소된 Coroutine에 대해 일시 중단을 해야 하는 경우 다음과 같이 withContext함수에 NonCancellable Context를 전달하여 사용하는 withContext(NonCancellable) { ... } 를 사용할 수 있다.
val job = launch {
try {
repeat(1000) { i ->
println("job: I'm sleeping $i ...")
delay(500L)
}
} finally {
withContext(NonCancellable) {
println("job: I'm running finally")
delay(1000L)
println("job: And I've just delayed for 1 sec because I'm non-cancellable")
}
}
}
delay(1300L) // delay a bit
println("main: I'm tired of waiting!")
job.cancelAndJoin() // cancels the job and waits for its completion
println("main: Now I can quit.")
📌 전체 코드는 이곳에서 확인할 수 있습니다.
📖 아래 내용은 독자의 이해를 위해 번역자가 추가한 글입니다.
*1. 이전 예제에서 finally 내부에서 delay를 사용하도록 바꾸어 본 코드
fun main() = runBlocking {
val job = launch {
try {
repeat(1000) { i ->
println("job: I'm sleeping $i ...")
delay(500L)
}
} catch (e: Exception) {
println(e)
} finally {
delay(1000L)
println("job: I'm running finally")
}
}
delay(1300L) // delay a bit
println("main: I'm tired of waiting!")
job.cancelAndJoin() // cancels the job and waits for its completion
println("main: Now I can quit.")
}
위 코드를 실행하면 아래와 같은 결과가 나온다. Cancellation Exception이 발생하는 것을 확인할 수 있다.
job: I'm sleeping 0 ...
job: I'm sleeping 1 ...
job: I'm sleeping 2 ...
main: I'm tired of waiting!
kotlinx.coroutines.JobCancellationException: StandaloneCoroutine was cancelled; job=StandaloneCoroutine{Cancelling}@9660f4e
main: Now I can quit.
이 글은 Coroutines 공식 문서를 번역한 글입니다.
원문 : Cancellation and timeouts - Run non-cancellable block
원문 최종 수정 : 2022년 6월 27일
목차로 돌아가기