with Context
状态的留档
使用给定的协程上下文调用指定的挂起块,挂起直到它完成,并返回结果。
但是,实际行为是它也在所有子协程上等待,并且不一定返回块的结果,而是在子协程中传播任何异常。
suspend fun main() {
try {
val result = withContext(coroutineContext) {
launch {
delay(1000L)
throw Exception("launched coroutine broke")
}
println("done launching")
42
}
println ("result: $result")
} catch (e: Exception) {
println("Error: ${e.message}")
}
}
我希望上面打印结果:42
,然后可能打印子协程的未捕获异常。相反,它等待一秒钟,然后打印错误:启动的协程已损坏
。
因此,实际行为与coroutineScope
构建器的行为相匹配。虽然它可能是一个有用的行为,但我认为它与留档相矛盾。留档是否应该更新为类似于coroutineScope
的东西?
一旦给定块及其所有子协程完成,此函数就会返回。
此外,这是否意味着我们可以互换使用coroutineScope
和with Context(coroutineContext)
,唯一的区别是样板少一点?
withContext
创建一个新作业。这意味着里面启动的所有协程都是这个作业的子协程。它只在作业完成时返回。由于结构化并发,它只在所有子协程也完成时完成。
当任何子作业失败时,父作业将被取消。这也将取消所有其他子作业。由于withContext
返回结果,因此引发异常。
CoroutineScope
的留档在这方面很有帮助:
每个协程构建器(如启动、异步等)和每个作用域函数(如coroutineScope、withContext等)都将自己的作用域与自己的Job实例一起提供到它运行的内部代码块中。按照惯例,它们都等待其块内的所有协程完成后再完成自己,从而强制执行结构化并发的纪律。
我认为with Context
的留档也可以改进。Job
和CoroutineContext
的留档非常有用,因为它们提供了更高级的观点。
此外,这是否意味着我们可以互换使用coroutineScope和withContext(coroutineContext),唯一的区别是样板文件少一点?
是的,它们应该以相同的方式运行。不过,它们适用于不同的用例。
coroutineScope
旨在为多个并行协程提供一个范围,如果有失败,所有协程都将被取消。
withContext
旨在用于切换给定代码块的上下文(例如Dispatcher)。
这是我最近在kotlin论坛上提出的一个类似的问题。该主题包含一些更多类似的案例和进一步的见解。
withcontext的行为是正确的。可以想象,如果发生异常,下面的代码无论如何都不会执行,除非您在该位置本身而不是在函数级别处理了异常。
当你启动一个协程函数,我们可以做这样的事情,
var job=启动{delay(1000L)抛出异常("启动的协程中断了")}job.调用On完成{异常-
加入
基本上,它将处理异常,不会传播到父协程。或者创建一个CoroutineExceptionHandler并将其传递给启动(CoroutineExceptionHandler)以自己处理它。