簡體   English   中英

CoroutineScope 與 SupervisorJob 與 supervisorScope

[英]CoroutineScope with SupervisorJob vs supervisorScope

最近我一直在詳細學習協程,據我所知,如果協程的一個子進程由於某種原因被取消, SupervisorJob()給了我們不取消所有子進程的機會。

據說以 coroutineScope 啟動的coroutineScope如果失敗會取消所有子進程,但以supervisorScope啟動的協程只會取消失敗的子進程

我想知道我是否可以通過將SupervisorJob作為 CoroutineContext 添加到它來更改CoroutineScope的行為,但是我無法獲得預期的行為,這是我沒有得到的

預期行為 - 打印 getData1() 和 getData3() 結果*

實際:- getData2() 取消所有協程

fun main() = runBlocking {

    val exceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable ->
        println(throwable)
    }

    val customScope = CoroutineScope(SupervisorJob() + exceptionHandler)


    customScope.launch {
        launch {
            getData1().also { println(it) }
        }
        launch {
            getData2().also { println(it) }
        }
        launch {
            getData3().also { println(it) }
        }
     }.join()

}


private suspend fun getData1(): String? {
    delay(1000)
    return "data 1"
}

private suspend fun getData2(): String? {
    delay(300)
    throw RuntimeException("While getting Data 2 exception happened")
}

private suspend fun getData3(): String? {
    delay(800)
    return "data 3"
}

您沒有在customScope中啟動三個內部協程。 您在已啟動的外部協程的 scope 中啟動它們(通過使用隱式this來啟動它們)。 如果您從具有 SupervisorJob 的自定義 scope 啟動它們,那么它應該可以工作:

launch {
    listOf(
        customScope.launch {
            getData1().also { println(it) }
        },
        customScope.launch {
            getData2().also { println(it) }
        },
        customScope.launch {
            getData3().also { println(it) }
        }
    ).joinAll()
}.join()

SupervisorJob 預期的行為,發生在我們使用來自根 scope 的 lunch/async 調用它時。

val job1 =rootscope.lunch{}
val job2 =rootscope.lunch{}
val job3 =rootscope.lunch{}

如果其中一項工作失敗,它不會影響其他工作,但是如果我們將它用作孩子,它的行為就像您的示例中的 Job() 一樣

但是,如果我需要孩子的協程表現得像“如果它從根作用域吃午飯”呢? . 就像你的例子,然后 supervisorScope 似乎解決了這個問題,如果你使用:

      customScope.launch {
        supervisorScope {
            launch {

                throw Exception()
            }
            launch {
                println("hjkhjk 111")
            }
            launch {
                println("hjkhjk 222")
            }
        }
    }.join()

然后每個子協程都以 rootScope.lunch{...} 運行,你的問題就解決了

暫無
暫無

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

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