用给定的协同上下文调用指定的挂起块,挂起直到完成,并返回结果。
然而,实际的行为是,它也等待所有子协同,不一定返回块的结果,而是在子协同中传播任何异常。
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}")
}
}
我希望上面的内容能够打印出result: 42
,然后,可能的话,从子代协同线中打印出不明显的异常。相反,它等待一秒钟,然后打印Error: launched coroutine broke
。
因此,实际行为与coroutineScope
构建器的行为相匹配。虽然这可能是一种有用的行为,但我认为它与文档相矛盾。文档是否应该更新为类似于coroutineScope
的内容?
该函数在给定块及其所有子协同器完成后立即返回。
此外,这是否意味着我们可以交替使用coroutineScope
和withContext(coroutineContext)
,唯一的区别是少一点样板?
发布于 2019-07-05 17:14:34
withContext
创建了一个新的作业。这意味着,所有在内部启动的合作项目都是这项工作的孩子。它只在工作完成后才返回。由于结构化并发,它只在所有子协同器也完成时才会完成。
当任何子作业失败时,父作业将被取消。这也将取消所有其他儿童工作。因为withContext
返回一个结果,所以会抛出异常。
文档 of CoroutineScope
在这方面很有帮助:
每个协同构建器(如启动、异步等)和每个作用域函数(如coroutineScope、withContext等)都在运行的内部代码块中提供自己的作业实例范围。按照约定,它们都要等待块中的所有协同器完成,然后才能完成自己的工作,从而执行结构化并发的规则。
我认为withContext
的文档也可以改进。Job
和CoroutineContext
的文档非常有用,因为它们提供了更高层次的观点。
此外,这是否意味着我们可以交替使用coroutineScope和withContext(coroutineContext),唯一的区别是少一点样板?
是的,他们的行为应该是一样的。不过,它们是针对不同的用例的。
coroutineScope
的目的是为多个并行协同线提供一个作用域,如果有任何失败,所有这些都将被取消。
withContext
被设计用来切换上下文(例如。(分配器)用于给定代码块。
这里是我最近在kotlin讨论论坛上提出的类似问题。这个线程包含了一些更相似的情况和进一步的洞察力。
发布于 2022-09-03 04:28:11
使用上下文的行为是正确的。想想看,如果出现异常,下面的代码将不会执行,除非您已经在该位置处理了异常,而不是在函数级别。
当你在内部启动一条协同线时,我们可以这样做,
job.invokeOnCompletion { exception -> println(“捕捉$exception") }}
job.join()
基本上,它将处理异常,而不会传播到父协同。或者创建一个CoroutineExceptionHandler并将其传递给启动(CoroutineExceptionHandler)来处理它本身。
https://stackoverflow.com/questions/56904057
复制相似问题