<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                **目錄** [TOC] ## 取消與超時 這一部分包含了協程的取消與超時。 ### 取消協程的執行 在一個長時間運行的應用程序中,你也許需要對你的后臺協程進行細粒度的控制。比如說,一個用戶也許關閉了一個啟動了協程的界面,那么現在協程的執行結果已經不再被需要了,這時,它應該是可以被取消的。該 [launch](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html) 函數返回了一個可以被用來取消運行中的協程的 [Job](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html): ```kotlin import kotlinx.coroutines.* fun main() = runBlocking { //sampleStart val job = launch { repeat(1000) { i -> println("job: I'm sleeping $i ...") delay(500L) } } delay(1300L) // 延遲一段時間 println("main: I'm tired of waiting!") job.cancel() // 取消該作業 job.join() // 等待作業執行結束 println("main: Now I can quit.") //sampleEnd } ``` > 可以在[這里](https://github.com/hltj/kotlinx.coroutines-cn/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-cancel-01.kt)獲取完整代碼。 程序執行后的輸出如下: ```text job: I'm sleeping 0 ... job: I'm sleeping 1 ... job: I'm sleeping 2 ... main: I'm tired of waiting! main: Now I can quit. ``` 一旦 main 函數調用了 `job.cancel`,我們在其它的協程中就看不到任何輸出,因為它被取消了。這里也有一個可以使 [Job](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html) 掛起的函數 [cancelAndJoin](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/cancel-and-join.html)它合并了對 [cancel](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/cancel.html)以及 [join](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/join.html)的調用。 ### 取消是協作的 協程的取消是 _協作_ 的。一段協程代碼必須協作才能被取消。所有 `kotlinx.coroutines` 中的掛起函數都是 _可被取消的_ 。它們檢查協程的取消,并在取消時拋出 [CancellationException](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html)。 然而,如果協程正在執行計算任務,并且沒有檢查取消的話,那么它是不能被取消的,就如如下示例代碼所示: ```kotlin import kotlinx.coroutines.* fun main() = runBlocking { //sampleStart val startTime = System.currentTimeMillis() val job = launch(Dispatchers.Default) { var nextPrintTime = startTime var i = 0 while (i < 5) { // 一個執行計算的循環,只是為了占用 CPU // 每秒打印消息兩次 if (System.currentTimeMillis() >= nextPrintTime) { println("job: I'm sleeping ${i++} ...") nextPrintTime += 500L } } } delay(1300L) // 等待一段時間 println("main: I'm tired of waiting!") job.cancelAndJoin() // 取消一個作業并且等待它結束 println("main: Now I can quit.") //sampleEnd } ``` > 可以在[這里](https://github.com/hltj/kotlinx.coroutines-cn/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-cancel-02.kt)獲取完整代碼。 運行示例代碼,并且我們可以看到它連續打印出了“I'm sleeping”,甚至在調用取消后,作業仍然執行了五次循環迭代并運行到了它結束為止。 ### 使計算代碼可取消 我們有兩種方法來使執行計算的代碼可以被取消。第一種方法是定期調用掛起函數來檢查取消。對于這種目的 [yield](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/yield.html)是一個好的選擇。另一種方法是顯式的檢查取消狀態。讓我們試試第二種方法。 將前一個示例中的 `while (i < 5)` 替換為 `while (isActive)` 并重新運行它。 ```kotlin import kotlinx.coroutines.* fun main() = runBlocking { //sampleStart val startTime = System.currentTimeMillis() val job = launch(Dispatchers.Default) { var nextPrintTime = startTime var i = 0 while (isActive) { // 可以被取消的計算循環 // 每秒打印消息兩次 if (System.currentTimeMillis() >= nextPrintTime) { println("job: I'm sleeping ${i++} ...") nextPrintTime += 500L } } } delay(1300L) // 等待一段時間 println("main: I'm tired of waiting!") job.cancelAndJoin() // 取消該作業并等待它結束 println("main: Now I can quit.") //sampleEnd } ``` > 可以在[這里](https://github.com/hltj/kotlinx.coroutines-cn/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-cancel-03.kt)獲取完整代碼。 你可以看到,現在循環被取消了。[isActive](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/is-active.html) 是一個可以被使用在[CoroutineScope](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html) 中的擴展屬性。 ### 在 `finally` 中釋放資源 我們通常使用如下的方法處理在被取消時拋出 [CancellationException](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html) 的可被取消的掛起函數。比如說,`try {……} finally {……}` 表達式以及 Kotlin 的 `use` 函數一般在協程被取消的時候執行它們的終結動作: ```kotlin import kotlinx.coroutines.* fun main() = runBlocking { //sampleStart val job = launch { try { repeat(1000) { i -> println("job: I'm sleeping $i ...") delay(500L) } } finally { println("job: I'm running finally") } } delay(1300L) // 延遲一段時間 println("main: I'm tired of waiting!") job.cancelAndJoin() // 取消該作業并且等待它結束 println("main: Now I can quit.") //sampleEnd } ``` > 可以在[這里](https://github.com/hltj/kotlinx.coroutines-cn/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-cancel-04.kt)獲取完整代碼。 [join](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/join.html)和 [cancelAndJoin](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/cancel-and-join.html) 等待了所有的終結動作執行完畢,所以運行示例得到了下面的輸出: ```text job: I'm sleeping 0 ... job: I'm sleeping 1 ... job: I'm sleeping 2 ... main: I'm tired of waiting! job: I'm running finally main: Now I can quit. ``` ### 運行不能取消的代碼塊 在前一個例子中任何嘗試在 `finally` 塊中調用掛起函數的行為都會拋出[CancellationException](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html),因為這里持續運行的代碼是可以被取消的。通常,這并不是一個問題,所有良好的關閉操作(關閉一個文件、取消一個作業、或是關閉任何一種通信通道)通常都是非阻塞的,并且不會調用任何掛起函數。然而,在真實的案例中,當你需要掛起一個被取消的協程,你可以將相應的代碼包裝在`withContext(NonCancellable) {……}` 中,并使用 [withContext](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-context.html) 函數以及 [NonCancellable](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-non-cancellable.html) 上下文,見如下示例所示: ```kotlin import kotlinx.coroutines.* fun main() = runBlocking { //sampleStart val job = launch { try { repeat(1000) { i -> println("job: I'm sleeping $i ...") delay(500L) } } finally { withContext(NonCancellable) { println("job: I'm running finally") delay(1000L) println("job: And I've just delayed for 1 sec because I'm non-cancellable") } } } delay(1300L) // 延遲一段時間 println("main: I'm tired of waiting!") job.cancelAndJoin() // 取消該作業并等待它結束 println("main: Now I can quit.") //sampleEnd } ``` > 可以在[這里](https://github.com/hltj/kotlinx.coroutines-cn/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-cancel-05.kt)獲取完整代碼。 ``` job: I'm sleeping 0 ... job: I'm sleeping 1 ... job: I'm sleeping 2 ... main: I'm tired of waiting! job: I'm running finally job: And I've just delayed for 1 sec because I'm non-cancellable main: Now I can quit. ``` ### 超時 在實踐中絕大多數取消一個協程的理由是它有可能超時。當你手動追蹤一個相關 [Job](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html) 的引用并啟動了一個單獨的協程在延遲后取消追蹤,這里已經準備好使用 [withTimeout](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-timeout.html) 函數來做這件事。 來看看示例代碼: ```kotlin import kotlinx.coroutines.* fun main() = runBlocking { //sampleStart withTimeout(1300L) { repeat(1000) { i -> println("I'm sleeping $i ...") delay(500L) } } //sampleEnd } ``` > 可以在[這里](https://github.com/hltj/kotlinx.coroutines-cn/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-cancel-06.kt)獲取完整代碼。 運行后得到如下輸出: ```text I'm sleeping 0 ... I'm sleeping 1 ... I'm sleeping 2 ... Exception in thread "main" kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 1300 ms ``` [withTimeout](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-timeout.html) 拋出了 `TimeoutCancellationException`,它是 [CancellationException](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html) 的子類。我們之前沒有在控制臺上看到堆棧跟蹤信息的打印。這是因為在被取消的協程中 `CancellationException` 被認為是協程執行結束的正常原因。然而,在這個示例中我們在 `main` 函數中正確地使用了 `withTimeout`。 由于取消只是一個例外,所有的資源都使用常用的方法來關閉。如果你需要做一些各類使用超時的特別的額外操作,可以使用類似 [withTimeout](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-timeout.html)的 [withTimeoutOrNull](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-timeout-or-null.html) 函數,并把這些會超時的代碼包裝在 `try {...} catch (e: TimeoutCancellationException) {...}`代碼塊中,而 [withTimeoutOrNull](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-timeout-or-null.html) 通過返回 `null` 來進行超時操作,從而替代拋出一個異常: ```kotlin import kotlinx.coroutines.* fun main() = runBlocking { //sampleStart val result = withTimeoutOrNull(1300L) { repeat(1000) { i -> println("I'm sleeping $i ...") delay(500L) } "Done" // 在它運行得到結果之前取消它 } println("Result is $result") //sampleEnd } ``` > 可以在[這里](https://github.com/hltj/kotlinx.coroutines-cn/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt)獲取完整代碼。 運行這段代碼時不再拋出異常: ```text I'm sleeping 0 ... I'm sleeping 1 ... I'm sleeping 2 ... Result is null ``` <!--- TEST --> <!--- MODULE kotlinx-coroutines-core --> <!--- INDEX kotlinx.coroutines --> [launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html [Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html [cancelAndJoin]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/cancel-and-join.html [Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/cancel.html [Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/join.html [CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html [yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/yield.html [isActive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/is-active.html [CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html [withContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-context.html [NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-non-cancellable.html [withTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-timeout.html [withTimeoutOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-timeout-or-null.html <!--- END -->
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看