🙇♂️
Kotlin CoroutineのTimeoutCancellationExceptionがcatchできない
TimeoutCancellationExceptionがcatchできない
withTimeout()を使ってcoroutineのタイムアウト処理を書いていた時、タイムアウトした時にwithTimeout()がthrowするTimeoutCancellationExceptionがcatchできずに少しハマりました。
catchできないコード例
try {
// withTimeout()がTimeoutCancellationExceptionをthrowしたとしても
withTimeout(1000) {
doWork()
}
} catch (e: CancellationException) {
// 1. こっちでcatchされる
println("cancelled")
} catch (e: TimeoutCancellationException) {
// 2. こっちでcatchできない
println("timeout")
}
上のコード例だと、tryの中でwithTimeout()がTimeoutCancellationExceptionをthrowしたとしても
2.ではcatchできずに1.でcatchされます。
なぜ?
理由は明確で、TimeoutCancellationExceptionはCancellationExceptionを継承しているからです(ドキュメント読め、という話ですが...)。
名前からしても推測できることですよね。
ドキュメントきちんと読まずに使っていたバチが当たりました...
どうすればよいか
以下のように、先にTimeoutCancellationExceptionをcatchするようにします。
try {
// withTimeout()がTimeoutCancellationExceptionをthrowすると
withTimeout(1000) {
doWork()
}
} catch (e: TimeoutCancellationException) {
// ちゃんとcatchできます
println("timeout")
} catch (e: CancellationException) {
// こっちは呼ばれません
println("cancelled")
}
ドキュメント読みます...
Discussion