在此代码中,为什么handler
仅打印JobCancellationException
而不是SocketException
的堆栈跟踪? foo
内的launch
函数肯定会抛出SocketException
,那么会发生什么呢?
suspend fun foo() {
val job = coroutineContext[Job]!!
val socket = Socket()
job.invokeOnCompletion(onCancelling = true) {
if (!socket.isClosed) {
socket.close()
}
}
// non-routable address -> timeout
// will throw SocketException after socket.close() is called above
socket.connect(InetSocketAddress("10.0.0.0", 1234), 2000)
}
fun test() = runBlocking {
val handler = CoroutineExceptionHandler { _, throwable ->
throwable.printStackTrace()
}
val job = launch(DefaultDispatcher + handler) {
foo()
}
delay(100)
job.cancelAndJoin()
delay(100)
}
答案 0 :(得分:0)
我无法告诉您为什么CoroutineExceptionHandler
没有捕获launch
中引发的异常。但是我可以告诉你两件事-
CoroutineExceptionHandler
中捕获异常。以下是显示如何捕获它的代码:
fun f() = runBlocking {
val eh = CoroutineExceptionHandler { _, e -> trace("exception handler: $e") }
val cs1 = CoroutineScope(Dispatchers.Default)
val j1 = cs1.launch(eh + CoroutineName("first")) {
trace("launched")
delay(1000)
throw RuntimeException("error!")
}
trace("joining j1")
j1.join()
val cs2 = CoroutineScope(Dispatchers.Default + eh)
val j2 = cs2.launch(CoroutineName("second")) {
trace("launched")
delay(1000)
throw RuntimeException("error!")
}
trace("joining j2")
j2.join()
trace("after join")
}
f()
控制台输出:
[main @coroutine#1]: joining j1
[DefaultDispatcher-worker-1 @first#2]: launched
[DefaultDispatcher-worker-1 @first#2]: exception handler: java.lang.RuntimeException: error!
[main @coroutine#1]: joining j2
[DefaultDispatcher-worker-1 @second#3]: launched
[DefaultDispatcher-worker-3 @second#3]: exception handler: java.lang.RuntimeException: error!
[main @coroutine#1]: after join
关键要点在于,如果您在自定义launch
上调用CoroutineScope
,则直接提供给CoroutineExceptionHandler
构造函数或CoroutineScope
的任何launch
在launch
ed协程中引发异常时执行。
希望有帮助!
更新
我发现了为什么没有捕获到异常的原因。请参阅我的答案here。