Mat*_*ans 5 kotlin kotlin-coroutines
我想在给定的parent中启动一个带有挂起函数的异步协程CoroutineScope,以生成一个Deferred可以从该范围内的任何协程使用的a。
我希望如果父级的作业被取消,它的作业也被取消,但是如果挂起函数抛出异常,我需要在结果中捕获该异常,Deferred而不取消父级范围中的同级作业。
我这样做的方式效果很好,但我想知道是否有比这更简单、更符合规范的方法:
fun <T> callIt(scope: CoroutineScope, block: suspend () -> T) : Deferred<T> {
val result = CompletableDeferred<T>()
scope.launch {
try {
result.complete(block())
} catch (e: Throwable) {
result.completeExceptionally(e)
}
}
return result
}
Run Code Online (Sandbox Code Playgroud)
我喜欢对挂起异常的处理block显然是我想要的,但我不太高兴构建async一个launch
不起作用的事情:
async捕获其异常,但作业仍然失败并取消其父作业。正如 @Rene 评论的: 的文档async说:“如果未能强制执行结构化并发范例,它会取消父作业(或外部范围)。”。您无需CompletableDeferred. 您需要创建一个作业SupervisorJob,并让其中的作业CoroutineScope成为新作业的父作业。如果范围被取消,async协程也会被取消。但 -coroutine 内的任何异常都async不会取消父作用域。
由于存在一个开放问题https://github.com/Kotlin/kotlinx.coroutines/issues/1578,我们需要显式完成 SupervisorJob。
fun <T> callIt(scope: CoroutineScope, block: suspend () -> T): Deferred<T> {
val supervisorJob = SupervisorJob(scope.coroutineContext[Job])
val deferred = scope.async(supervisorJob) {
block()
}
deferred.invokeOnCompletion {
supervisorJob.complete()
}
return deferred
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
632 次 |
| 最近记录: |