繁体   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