Возможность отмены функции приостановки Kotlin

#kotlin

#kotlin

Вопрос:

Я хочу сделать функцию приостановки отменяемой, но isActive она недоступна. Это просто обрабатывается автоматически?

 suspend fun coolFunction() {
    while (isActive) {
        /* Do cool stuff */
    }
}
  

Ответ №1:

Для совместной работы с отменой можно периодически приостанавливать, что проще всего сделать, вызвав yield()

 suspend fun coolFunction() {
    while (true) {
        yield()
        /* Do cool stuff */
    }
}
  

Вы также можете поддерживать отмену, установив флажок CoroutineScope.isActive . Но функция приостановки сама по себе не имеет прямого доступа к сопрограмме, из которой она была вызвана. Вам пришлось бы использовать что-то вроде coroutineContext[Job]!!.isActive , что является неуклюжим. isActive более полезно, когда вы непосредственно составляете сопрограмму с чем-то вроде launch , а не с suspend функцией, которая может быть вызвана из любой области.

Ответ №2:

Вы можете отменить задание или сопрограмму, в которой выполняется функция приостановки, чтобы функция приостановки была отменена.

 private suspend fun CoroutineScope.cancelComputation() {

    println("cancelComputation()")

    val startTime = System.currentTimeMillis()
    val job = launch(Dispatchers.Default) {
        var nextPrintTime = startTime
        var i = 0

        // WARNING 🔥 isActive is an extension property that is available inside
        // the code of coroutine via CoroutineScope object.

        while (isActive) { // cancellable computation loop
            // print a message twice a second
            if (System.currentTimeMillis() >= nextPrintTime) {
                println("I'm sleeping ${i  } ...")
                nextPrintTime  = 500L
            }
        }
    }
    delay(1300L) // delay a bit
    println("main: I'm tired of waiting!")
    job.cancelAndJoin() // cancels the job and waits for its completion println("main: Now I can quit.")

    /*
        Prints:
        cancelComputation()
        I'm sleeping 0 ...
        I'm sleeping 1 ...
        I'm sleeping 2 ...
        main: I'm tired of waiting!
     */

}
  

Комментарии:

1. Однако как функция отменяется? Что, если у него есть несколько открытых ресурсов, которые он должен закрыть? Это просто сбой и запись при отмене задания?

2. Официальные документы — одно из лучших, из которых вы можете узнать, как работают сопрограммы, здесь вы можете это проверить, и я предлагаю учиться flow после сопрограмм, если вас интересует реактивное программирование.

3. Я просмотрел официальные документы, они на самом деле не говорят мне, что я хочу знать. Например, они говорят, что встроенные функции, такие как delay , будут генерировать исключение отмены при отмене его сопрограммы. Итак, как эта функция узнает, когда она отменяется? Это в основном то, что я хотел бы знать. flow я не думаю, что это действительно применимо. Мои функции выполняют потенциально длительный процесс, а затем возвращают одно значение.

4. Если вы работаете с ресурсами, вам нужно использовать try-finally или Closeable.use как обычно, чтобы очистить ресурсы в случае отмены.

5. Значит, он перейдет к finally, если он будет отменен? В официальных документах указано, что цикл, который не проверяет отмену, будет продолжаться вечно (или, по крайней мере, до тех пор, пока цикл не завершится естественным образом).