Выбор ответа Senior Корутины и structured concurrency обновлено

Проглоченный CancellationException

Вопрос

Чем опасен этот код?

scope.launch {
    while (true) {
        try {
            delay(1000)
            refresh()
        } catch (e: Exception) {
            log(e)
        }
    }
}

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: catch поймает отмену, и корутина продолжит цикл. Отмена в корутинах реализована исключением CancellationException, и catch (e: Exception) его тоже ловит.

Варианты ответа

  1. Ничем, это правильная обработка ошибок в цикле
  2. delay нельзя вызывать внутри try, он не отменяется
  3. catch поймает отмену, и корутина продолжит циклправильный ответ
  4. Исключения в корутинах не ловятся обычным try

Разбор

Отмена в корутинах реализована исключением CancellationException, и catch (e: Exception) его тоже ловит. Корутина «не замечает» отмены и продолжает работать, нарушая structured concurrency. Правильно ловить конкретные исключения или перебрасывать CancellationException: catch (e: CancellationException) { throw e }, либо вызывать ensureActive() после catch. try вокруг suspend-вызовов работает нормально.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.