본문 바로가기
Android

[Coroutine] 취소와 타임아웃(1) - cancel

by Diane_KIM 2024. 5. 6.

 cancel 

launch(코루틴 빌더)의 리턴값인 Job을 명시적으로 취소할 수 있는 메서드
단, 코루틴을 취소하려면 suspension point가 있어야한다.
// 1번 Case
suspend fun doOne() = coroutineScope {
    val job = launch { 
        println("launch1")
        delay(1000L)
        println("1!")
    }
    delay(300L)
    job.cancel()
    println("2!")
}

fun main() = runBlocking {
	doOne()
    println("3!")
}
// 2번 case
suspend fun doCount() = coroutineScope {
    val job = launch(Dispatchers.Default) { 
        var i = 1
        var nextTime = System.currentTimeMillis() + 100L
        while (i <= 10) {
            val currentTime = System.currentTimeMillis()
            if(currentTime >= nextTime) {
                println(i)
                nextTime = currentTime + 100L
                i++
            }
        }
    }
    
    delay(200L)
    job.cancel()
    println("doCount Done!")
}

fun main() = runBlocking {
    doCount()
}
 
1번 case는 job이 취소되어 2!3!2번 case는 job이 취소되지 않아 1! 2! doCount Done! 3! ~ 10! 모두 출력된다
  • 2번이 취소가 되지 않는 이유는 suspension point(delay)가 없기 때문이다

 

 Q.  2번 케이스에서 job이 모두 끝난 후에 doCount Done!을 출력하려면?

 join을 이용해 cancel 함수가 실제로 취소될때까지 기다려주고 그 다음에 doCount Done!을 호출하도록 한다.

delay(200L)
job.cancel()
job.join()
println("doCount Done!")

 

이렇게 되면 1! 2! 3! ~ 10!까지 모두 호출이 된 다음에 doCount Done!이 호출된다. 

또한 job.cancel() 과 job.join()을 한번에 사용할 수 있는 job.cancelAndJoin() 함수도 있다.

 

 Q.  2번케이스에서 job을 취소 하려면?

isActive 속성을 사용하여 코루틴의 실행 코드 내에서 취소 상태를 주기적으로 확인함으로써 루프문을 통과하지 못하도록 해야 함

  • isActive는 코루틴의 현재 활성 상태를 나타내며, 취소되면 false가 된다
 while (i <= 10 && isActive) {
        ...
}