英文:
Child Jobs don't cancell scope in Kotlin coroutines
问题
我正在尝试了解有关作业(Jobs)中的取消传播的信息。我认为如果一个作业被取消了,它的父作业也会被取消。
val cancellableScope = CoroutineScope(Dispatchers.Default + Job())
val cancellableScope2 = CoroutineScope(Dispatchers.Default + Job())
runBlocking {
cancellableScope2.launch {
cancellableScope.launch {
throw Error("1")
}.join()
cancellableScope.launch {
println("2")
}.join()
}.join()
cancellableScope2.launch {
delay(200)
println("3")
}.join()
}
我得到了以下输出:
Exception in thread "DefaultDispatcher-worker-2" java.lang.Error: 1
at MainKt$main$1$1$1.invokeSuspend(Main.kt:21)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@430de60, Dispatchers.Default]
3
我期望只会得到错误信息,但也打印出了 "3"。难道不是当第一个启动失败时,“cancellableScope2” 也会被取消吗?
我尝试改成相同的上下文。
英文:
I'm trying to learn about cancel propagation in Jobs. I thought if a Job get's cancelled, its father too.
val cancellableScope = CoroutineScope(Dispatchers.Default + Job())
val cancellableScope2 = CoroutineScope(Dispatchers.Default + Job())
runBlocking {
cancellableScope2.launch {
cancellableScope.launch {
throw Error("1")
}.join()
cancellableScope.launch {
println("2")
}.join()
}.join()
cancellableScope2.launch {
delay(200)
println("llegó 3")
}.join()
}
I get the next output:
Exception in thread "DefaultDispatcher-worker-2" java.lang.Error: 1
at MainKt$main$1$1$1.invokeSuspend(Main.kt:21)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@430de60, Dispatchers.Default]
3
I expected to only get the error, but "3" get's printed too. Isn't "cancellableScope2" cancelled when first launched fails too?
I tried changing to the same context
答案1
得分: 1
尽管您在cancellableScope2.launch
范围中启动,但在此处启动时使用了显式的父范围:
cancellableScope2.launch {
cancellableScope.launch {
throw Error("1")
}.join()
cancellableScope.launch {
println("2")
}.join()
}.join()
这意味着这些作业仅是cancellableScope
的子孙作业,与cancellableScope2
没有关系,因此它们可以自由地崩溃,而不会影响scope2
的状态。
您可能会感到困惑的是launch
启动的作业不会返回任何结果。您在它们上面执行join
,但这只是等待它们完成。它们成功、失败或被取消都无关紧要。
但是,如果您使用 async
和 await
而不是 launch
+ join
,您将获得您期望的行为。这会创建一个返回结果的 Deferred
,因此在这种情况下,await
将重新抛出 Error(1)
,从而会崩溃 scope2
。
英文:
Even though you're in cancellableScope2.launch
scope you use explicit parent scope when launching here:
cancellableScope2.launch {
cancellableScope.launch {
throw Error("1")
}.join()
cancellableScope.launch {
println("2")
}.join()
}.join()
That means those jobs are descendant of cancellableScope
only and have no relation to cancellableScope2
, so they are free to collapse without affecting state of scope2
.
The thing you might be confused about is that launch
-ed jobs don't return any result. You do join
on them but it's just a delay until they're complete. Whether they succeed, fail or get cancelled doesn't matter.
However if instead of launch
+ join
you use async
and await
you'll get the behavior you expect. That creates a Deferred
which does return a result so in this case await
would rethrow Error(1)
which will collapse scope2
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论