【问题标题】:Making Kotlin Suspend Function Cancellable使 Kotlin 挂起函数可取消
【发布时间】:2020-09-23 20:48:00
【问题描述】:

我想取消挂起功能,但无法访问 isActive。这是自动处理的吗?

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

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    配合取消,可以定期挂起,最简单的方法是调用yield()

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

    您还可以通过选中CoroutineScope.isActive 来支持取消。但是挂起函数本身并不能直接访问调用它的 CoroutineScope。您将不得不使用类似coroutineContext[Job]!!.isActive 的东西,这很笨拙。当您直接使用 launch 之类的东西而不是可以从任何范围调用的 suspend 函数来编写协程时,isActive 会更有用。

    【讨论】:

      【解决方案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!
           */
      
      }
      

      【讨论】:

      • 该功能如何取消?如果它有一些应该关闭的开放资源怎么办?取消作业时它会崩溃和燃烧吗?
      • 官方文档是您可以了解协程如何工作的最好的文档之一,here 您可以查看它,如果您对响应式编程感兴趣,我建议您学习 flowafter coroutines。跨度>
      • 我查看了官方文档,他们并没有真正告诉我我想知道什么。例如,他们说像delay 这样的内置函数会在其协程被取消时抛出取消异常。那么该函数如何知道它何时被取消呢?这基本上就是我想知道的。 flow 并不适用,我不认为。我的函数执行了一个可能需要长时间运行的过程,然后返回一个值。
      • 如果你正在使用资源,你需要像往常一样使用try-finally或Closeable.use,这样如果取消它会清理资源。
      • 如果取消了会跳到finally吗?官方文档表明,不检查取消的循环将永远继续(或至少直到循环自然结束)。
      猜你喜欢
      • 2021-10-02
      • 2020-01-27
      • 2018-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-20
      相关资源
      最近更新 更多