코루틴의 취소 전파를 위해 이용되는 CancellationException은 IllegalStateException을 상속받는다.
즉, try-catch 혹은 runCatching 을 통해 작업할 때 CancellationException 에 대한 수동 처리를 하지 않으면,
코루틴의 정상적인 취소 흐름이 왜곡될 수 있다. 결과적으로 취소가 단순 실패처럼 보이거나, 취소 전파가 막혀버리는 문제가 발생할 수 있다.
이를 위해서는 별도 처리를 해줘야 한다.
CancellationException 은 실패가 아니라 정상적인 취소 신호이다.
하지만 try-catch, runCatching 은 모든 예외를 잡아버리기 때문에, 취소도 일반 실패처럼 취급하기 때문에,이 예외를 만나면 반드시 재던지기(rethrow) 하여 취소 흐름을 유지해야 한다.
launch {
try {
doWork()
} catch (e: CancellationException) {
throw e // 취소는 전파
} catch (e: Exception) {
...
}
}
val result = runCatching {
doWork()
}.onFailure { e ->
if (e is CancellationException) throw e
}
val result = withContext(Dispatchers.IO) {
try {
fetchRemoteData()
} catch (e: CancellationException) {
throw e
} catch (e: Exception) {
...
}
}
inline fun <R> runCatchingCancellable(block: () -> R): Result<R> = runCatching(block).onFailure { e ->
if (e is CancellationException) throw e
}
val result = runCatchingCancellable { doWork() }