簡體   English   中英

Kotlin Coroutine Supervisor作業取消行為

[英]Kotlin Coroutine SupervisorJob canceling behaviour

代碼:

viewModelScope.launch(CoroutineExceptionHandler { _, _ ->
                Log.e("TAG", "task 1")
            }) {
                try {
                    Log.e("TAG", "task 1 start")
                    delay(3000)
                    Log.e("TAG", "task 1 finished")
                } catch (ex: Exception) {
                    Log.e("TAG", "task 1 cancelled " + ex)
                }
            }

    launch = viewModelScope.launch(CoroutineExceptionHandler { _, _ ->
        Log.e("TAG", "handler 1" + myJob?.isCancelled)
    }) {

        myJob = SupervisorJob()
        launch(myJob!! + CoroutineExceptionHandler { _, _ ->
            Log.e("TAG", "handler 2 " + myJob?.isCancelled)
        }) {

            delay(300)
            launch {
                try {
                    Log.e("TAG", "task 2 start")
                    delay(5000)
                    Log.e("TAG", "task 2 finished")
                } catch (ex: Exception) {
                    Log.e("TAG", "task 2 ex " + ex)
                }
            }

            launch {
                delay(2000)
                throw Exception()
            }

        }

        launch {
            try {
                Log.e("TAG", "task 3 start")
                delay(3000)
                Log.e("TAG", "task 3 finished")
            } catch (ex: Exception) {
                Log.e("TAG", "task 3 ex " + ex)
            }
        }
    }

輸出:

2020-01-06 09:47:56.462 7159-7159/? E/TAG: task 1 start
2020-01-06 09:47:56.496 7159-7159/? E/TAG: task 3 start
2020-01-06 09:47:56.798 7159-7159/com.mvvm.template.debug E/TAG: task 2 start
2020-01-06 09:47:58.822 7159-7159/com.mvvm.template.debug E/TAG: task 2 ex kotlinx.coroutines.JobCancellationException: Parent job is Cancelling; job=StandaloneCoroutine{Cancelling}@81a8e39
2020-01-06 09:47:58.827 7159-7159/com.mvvm.template.debug E/TAG: handler 2 false
2020-01-06 09:47:59.464 7159-7159/com.mvvm.template.debug E/TAG: task 1 finished
2020-01-06 09:47:59.499 7159-7159/com.mvvm.template.debug E/TAG: task 3 finished

我的問題:

我很難理解為什么任務 2 在它是 SupervisorJob 的孩子並且異常發生在另一個孩子身上時被取消。

文檔狀態:

一個孩子的失敗或取消不會導致主管工作失敗,也不會影響其其他孩子,因此主管可以實施自定義策略來處理其孩子的失敗。 我錯過了什么還是什么? 任何幫助,將不勝感激。

您的答案就在日志中:

task 2 ex kotlinx.coroutines.JobCancellationException: Parent job is Cancelling;
job=StandaloneCoroutine{Cancelling}@81a8e39

看看父作業:它是一個StandaloneCoroutine而不是你的SupervisorJob

當你寫

launch(myJob!!, handler) { ... }

myJob成為啟動的協程的父級,並且協程本身始終與launch函數為其創建的作業相關聯,類型為StandaloneCoroutine 在此協程中,您無需明確指定父級即可啟動更多協程,這意味着它們的父級是協程的工作。 它不是主管工作並被取消。

我很難理解為什么任務 2 在它是 SupervisorJob 的孩子並且異常發生在另一個孩子身上時被取消。

這不是問題的直接答案,因為它已經被接受的答案很好地回答了,因為父母不是SupervisorJob

但是為了實現使 task2 獨立於兄弟作業的預期行為:

您必須通過以下任一方式使用SupervisorJob

  1. 使SupervisorJob成為您希望彼此獨立的每個任務的父項:

在您的示例中:

val myJob = SupervisorJob()
    val launch = viewModelScope.launch(CoroutineExceptionHandler { _, _ ->
        Log.e("TAG", "handler 1" + myJob.isCancelled)
    }) {

        launch(CoroutineExceptionHandler { _, _ ->
            Log.e("TAG", "handler 2 " + myJob.isCancelled)
        }) {

            delay(300)
            launch(myJob) { // <<<<<<<<< myJob is the parent
                try {
                    Log.e("TAG", "task 2 start")
                    delay(5000)
                    Log.e("TAG", "task 2 finished")
                } catch (ex: Exception) {
                    Log.e("TAG", "task 2 ex $ex")
                }
            }

            launch(myJob) { // <<<<<<<<< myJob is the parent
                delay(2000)
                throw Exception()
            }

        }

        //......
    }
  1. supervisorScope掛起函數中添加子作業兄弟
val launch = viewModelScope.launch(CoroutineExceptionHandler { _, _ ->
    Log.e("TAG", "handler 1")
}) {
    launch(CoroutineExceptionHandler { _, _ ->
        Log.e("TAG", "handler 2 ")
    }) {

        delay(300)

        supervisorScope { /// <<<< supervisor scope
            launch {
                try {
                    Log.e("TAG", "task 2 start")
                    delay(5000)
                    Log.e("TAG", "task 2 finished")
                } catch (ex: Exception) {
                    Log.e("TAG", "task 2 ex $ex")
                }
            }

            launch {
                delay(2000)
                throw Exception()
            }
        }

    }

    //....
}

現在任務 2將在不引發JobCancellationException情況下完成

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM