我很困惑如何正确取消协程任务。 测试案例很简单,我有一个类,其中包含两个方法:
class CancellationTest {
private var job: Job? = null
private var scope = MainScope()
fun run() {
job?.cancel()
job = scope.launch { doWork() }
}
fun doWork() {
// gets data from some source and send it to BE
}
}
方法doWork
有一个api调用,它是暂停的
并且尊重取消
。
在上面的例子中,当计算成功发送到后端的对象后,我可以看到很多重复项,这意味着cancel
并没有真正地取消
之前的调用。
然而,如果我使用在互联网上找到的片段
internal class WorkingCancellation<T> {
private val activeTask = AtomicReference<Deferred<T>?>(null)
suspend fun cancelPreviousThenRun(block: suspend () -> T): T {
activeTask.get()?.cancelAndJoin()
return coroutineScope {
val newTask = async(start = CoroutineStart.LAZY) {
block()
}
newTask.invokeOnCompletion {
activeTask.compareAndSet(newTask, null)
}
val result: T
while (true) {
if (!activeTask.compareAndSet(null, newTask)) {
activeTask.get()?.cancelAndJoin()
yield()
} else {
result = newTask.await()
break
}
}
result
}
}
}
它正常工作,对象不会重复并且已正确发送到BE。
最后一件事是我在for循环
中调用run
方法-但无论如何,我不确定为什么job?.cancel
不能正常工作,而WorkingCancellation
实际上正在工作。