[英]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
:
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()
}
}
//......
}
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.