#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, если он будет отменен? В официальных документах указано, что цикл, который не проверяет отмену, будет продолжаться вечно (или, по крайней мере, до тех пор, пока цикл не завершится естественным образом).