英文:
Why try/catch behavior is different in a coroutine scope and in a simple suspending function (Kotlin)?
问题
在尝试管理在协程上重新抛出异常时,我最终理解到在挂起函数中我们可以像通常一样使用try/catch(感谢 @Tenfour04)。
fun main(): Unit = runBlocking {
launch {
doAction()
}
launch {
delay(2000)
println("Printed2")
}
}
suspend fun doAction() {
try {
delay(1000)
throw Error("Some error")
} catch (e: Throwable) { // 不,这里不起作用
println("Printed1")
}
}
// Printed1
// Printed2
但困扰我的是(并使我不当地使用了CoroutineExceptionHandler),在以下代码中,try/catch不像通常那样起作用,因为异常会终止协程:
fun main(): Unit = runBlocking {
// 不要在这里包裹try-catch。它将被忽略。
try {
launch {
delay(1000)
throw Error("Some error")
}
} catch (e: Throwable) { // 不,这里不起作用
println("不会被打印")
}
launch {
delay(2000)
println("不会被打印")
}
}
// Exception in thread "main" java.lang.Error: Some error...
在这两种情况下,我们都处于协程上下文中。区别在于:
- 第一个没有协程作用域
- 第二个有协程作用域
我不太清楚为什么在这两种情况下try/catch的行为不同。
英文:
As I tried to managed the rethrow in a coroutine context, I finally understood that in suspending function we can use try/catch as usual (thanks @Tenfour04).
fun main(): Unit = runBlocking {
launch {
doAction()
}
launch {
delay(2000)
println("Printed2")
}
}
suspend fun doAction() {
try {
delay(1000)
throw Error("Some error")
} catch (e: Throwable) { // nope, does not help here
println("Printed1")
}
}
// Printed1
// Printed2
But what was confusing me (and make me use badly the CoroutineExceptionHandler) is in the following code the try/catch is not working as usual, as the exception kills the coroutine :
fun main(): Unit = runBlocking {
// Don't wrap in a try-catch here. It will be ignored.
try {
launch {
delay(1000)
throw Error("Some error")
}
} catch (e: Throwable) { // nope, does not help here
println("Will not be printed")
}
launch {
delay(2000)
println("Will not be printed")
}
}
// Exception in thread "main" java.lang.Error: Some error...
In both case, we are in a coroutine context. The difference is :
- the first one has not a coroutine scope as this
- the second one as coroutine scope as this
I'm not very clear of why the try/catch behavior is different in the both cases
答案1
得分: 0
我明白了。这是因为try/catch在协程之外。如果我更改try/catch和launch,异常不会终止协程。
import kotlinx.coroutines.*
import kotlinx.coroutines.runBlocking
fun main(): Unit = runBlocking {
// 不要在这里包装try-catch。它会被忽略。
launch {
try {
delay(1000)
throw Error("Some error")
} catch (e: Throwable) { // 不,这里不起作用
println("不会被打印出来")
}
}
launch {
delay(2000)
println("不会被打印出来")
}
}
抱歉,这很明显。
Tenfour04在之前的问题中告诉了我,但我没有明白。
Stackoverflow是一个好的心灵疗法
英文:
Ok I understood. This is because the try/catch is outside of coroutine. If I change the try/catch and the launch, the exception not kill the coroutine.
import kotlinx.coroutines.*
import kotlinx.coroutines.runBlocking
fun main(): Unit = runBlocking {
// Don't wrap in a try-catch here. It will be ignored.
launch {
try {
delay(1000)
throw Error("Some error")
} catch (e: Throwable) { // nope, does not help here
println("Will not be printed")
}
}
launch {
delay(2000)
println("Will not be printed")
}
}
Sorry, it was so evident.
Tenfour04 told me in the previous question, but I did’t get that.
Stackoverflow is a good therapy
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论