이번 글에서는 코루틴을 취소할 때 어떤 취소 방법을 취해야하는지에 대해 설명해본다.
코루틴 안에서 반복문을 실행하는 도중 취소하는 상황을 예시로 보자.
코드 예제
fun main() = runBlocking {
val job = launch(Dispatcher.Default) {
repeat(10) { index ->
println("repeat $index")
Thread.sleep(100)
}
}
delay(250)
println("Cancel coroutine")
job.cancel()
}
위 예제를 실행한 결과를 먼저 예상해보자.
만약 이 코드가 정상적으로 repeat 0~2까지만 실행됐을거라고 생각했다면 오산이다.
취소되지 않는 이유
250밀리초 이후 cancel 신호를 주게 되지만 이를 받아서 처리할 부분이 반복문 내부에 없기 때문이다.
이게 무슨 뜻일까. 다시 상기시켜보자.
코루틴이 취소되는 순서는 간단히 CancellationException을 받아 코루틴이 종료되는 것이라고 할 수 있다.
여기서 delay는 suspend function이지만, Thread.sleep은 suspend function이 아니다.
코루틴 내부에서 suspend function을 사용하지 않는다면 외부에서 cancel을 호출해도
내부에서 CancellationException을 발생시킬 지점이 없다는 의미이다.
그렇다면 어떤 함수로 코루틴 취소를 알 수 있을까?
당연히 Thread.sleep을 delay로 바꾸면 된다고 생각할 수 있지만, 그 답은 제외하고 생각해보자.
반복문 제일 처음에 취소 여부를 확인하는 방법이 있을 것이다.
이 때 사용할 수 있는 함수는 ensureActive()와 yield()가 있다.
두 함수 모두 CancellationException을 발생시킬 수 있다.
ensureActive 함수는 이름 그대로
코루틴의 active 여부를 판단하고 CancellationException을 발생시킨다.
yield 함수는 다른 코루틴이 실행될 수 있도록 양보하는 역할을 하지만,
코루틴이 취소된 경우 CancellationException을 발생시킨다.
마지막으로 함수가 아닌 프로퍼티 접근으로도 확인하는 방법이 있다.
바로 isActive 프로퍼티이다.
현재 코루틴이 complete와 cancel 상태가 아니라면 해당 프로퍼티는 true 값을 가지고 있다.
수정된 코드
fun main() = runBlocking {
val job = launch(Dispatcher.Default) {
repeat(10) { index ->
// if (isActive) {
// println("repeat $index")
// Thread.sleep(100)
// } else {
// throw CancellationException()
// }
// yield()
// ensureActive()
println("repeat $index")
Thread.sleep(100)
}
}
delay(250)
println("Cancel coroutine")
job.cancel()
}
참조
https://kotlinlang.org/docs/cancellation-and-timeouts.html#making-computation-code-cancellable
Cancellation and timeouts | Kotlin
kotlinlang.org
'Language > Kotlin' 카테고리의 다른 글
NonCancellable Coroutines 사용해보기 (0) | 2025.04.07 |
---|---|
LifecycleScope 간단히 알아보기 (0) | 2025.02.26 |
ViewModelScope 알아보기 (1) | 2025.02.25 |
GlobalScope 알아보기 (0) | 2025.02.17 |
Structured Concurrency in Coroutines (1) | 2025.01.19 |