Что такое прерывание у корутин

Ответ

Прерывание (cancellation) в корутинах — это механизм для остановки выполнения корутины до её завершения. Корректная отмена важна для избежания утечек ресурсов.

Как работает:

  • Вызывается cancel() на Job или CoroutineScope
  • Устанавливается флаг isActive = false
  • Корутина бросает CancellationException (не ловится в try/catch)

Пример:

val job = launch {
    try {
        repeat(1000) { i ->
            ensureActive() // Проверка отмены
            delay(100)
        }
    } finally {
        // Очистка ресурсов
    }
}
job.cancel() // Прерывает выполнение

Важно:

  • Отмена кооперативна — корутина должна проверять isActive или вызывать yield()/ensureActive()
  • finally блок выполняется даже при отмене

Ответ 18+ 🔞

А, слушай, про прерывание корутин. Ну это такая штука, чтобы твоя асинхронная хуйня не висела вечно, если она уже не нужна. Представь, ты запустил фоновую задачу, а пользователь уже на другую вкладку ушёл. Ну и зачем её дальше гонять? Вот чтобы ресурсы не жрала почём зря, её надо прибить. Это и есть cancellation.

Как эта магия работает, ёпта:

  • Ты вызываешь cancel() на этом самом Job или на всей области видимости (CoroutineScope). Это как крикнуть "СТОП, БЛЯДЬ!".
  • Внутри корутины флажок isActive падает в false. Всё, приплыли.
  • И самое главное — корутина кидает CancellationException. Но это не обычная ошибка, её в try/catch не поймаешь, она тихая, специальная, чтобы просто выполнение обрубить.

Вот смотри, как на практике выглядит:

val job = launch { // Запустили дело
    try {
        repeat(1000) { i -> // Хотели тыщу раз что-то сделать
            ensureActive() // <-- Вот это критически важно! Спросил: "Меня не отменили ещё?"
            delay(100) // Потупили чутка
        }
    } finally {
        // А вот тут, в finally, делаешь уборку. Даже если тебя прервали, этот блок выполнится.
        // Закрываешь файлы, сокеты, коннекты — всё, что надо почистить.
    }
}
// ...прошло полсекунды, а нам это уже не надо
job.cancel() // БАЦ! И всё, выполнение корутины нахуй прервано.

Но тут, чувак, есть один важнейший нюанс, про который все забывают:

Отмена — она кооперативная, блядь! Это не как процесс прибить — операционка его вырежет из памяти против его воли. А тут корутина должна сама вежливо проверять, не отменили ли её. Если она ушла в долгий цикл без delay() и не проверяет isActive или не вызывает yield() / ensureActive() — то можешь её cancel() хоть сто раз вызывать, она будет работать, пока сама не закончит. Это пиздец как важно понимать.

И да, finally-блок — это святое. Даже если тебя отменили, уборку за собой сделать дадут. Иначе получишь утечку ресурсов, а это, ядрёна вошь, никому не нужно.

Короче, запомни: запустил — будь добр, предусмотри и корректную остановку. А то будет тебе не корутина, а вечный двигатель в памяти.