【问题标题】:Kotlin Coroutine How to cancel async await()Kotlin Coroutine 如何取消异步 await()
【发布时间】:2020-09-28 00:08:15
【问题描述】:

我一直在尝试将协程应用于我的 android 应用程序,但发现异步协程有些奇怪。基于此article

val deferred = async { … }
deferred.cancel()
val result = deferred.await() // throws JobCancellationException!

如果在调用 await 代码之前取消延迟,它会抛出异常。似乎它只是不允许您取消异步协程。如何取消延迟而不抛出异常?

或者唯一的方法就是在每次等待时添加 try-catch?但这对我来说似乎很冗长。有没有更清洁的方法?

【问题讨论】:

  • 这篇文章有一个确切的答案:Cancellation in coroutines,“Job.join vs Deferred.await cancelling”部分。那里描述的代码(和行为)与您的完全相同。
  • 你到底想达到什么目的?如果您想等待取消的协程完成,您应该加入,如文章中所述。请澄清您的问题。
  • @madhead,我来自那篇文章。我已经稍微编辑了这个问题。抱歉,我希望这次更有意义。
  • @alediaferia 抱歉这个令人困惑的问题,希望现在它更有意义。
  • 那么,你有没有看到这个:“这就是为什么我们会得到这个异常:await 的作用是暂停协程,直到计算出结果;由于取消了协程,所以结果不能计算。因此,在取消之后调用 await 会导致 JobCancellationException”。你有什么不清楚的地方?

标签: kotlin async-await kotlin-coroutines coroutine deferred


【解决方案1】:

cancel() 之后调用await() 会导致CancellationException。来自await()方法的docs

这个暂停功能是可以取消的。如果当前的Job 在此挂起功能执行时,协程被取消或完成 等待,此功能立即以CancellationException 恢复。

CancellationException 被“静默”抛出不会导致应用崩溃,我们可以从docs 中读取:

如果异常是CancellationException,那么它会被忽略(因为 是取消正在运行的协程的假定机制)

如果您想以某种方式处理异常、清理资源或希望您的代码在调用 await() 后继续执行,请照常使用 try-catch 块:

val deferred = async { ... }
deferred.cancel()
try {
    val result = deferred.await()
} catch (e: CancellationException) {
    // handle CancellationException if need
} finally {
    // make some cleanup if need
}

// ... other code which will be executed if `await()` throws `CancellationException`

【讨论】:

    猜你喜欢
    • 2019-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多