kotlin - 为什么 CoroutineExceptionHandler 没有捕获/处理我的异常?
问题描述
在这段代码中,为什么handler
只打印堆栈跟踪JobCancellationException
而不是SocketException
?里面的foo
函数launch
肯定是 throws 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)
}
解决方案
我不能告诉你为什么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
custom CoroutineScope
,任何CoroutineExceptionHandler
直接提供给CoroutineScope
构造函数或 to 的launch
内容都会在launch
ed 协程中引发异常时执行。
希望有帮助!!
更新
我发现了为什么没有捕获异常。在这里查看我的答案。
推荐阅读
- python - 获取非连续熊猫时间戳的频率
- symfony - 验证对象 Symfony 4.2 的 CollectionType 数组
- node.js - 使用 Atom 远程调试 Meteor / Nodejs
- docker - 如果有 root 运行的命令,我如何检查 docker 映像
- php - 在 PHP 中获取保存在 vb.net 和 ICSharpCode.SharpZipLib.Zip.ZipInputStream 中的图像
- python - 从文本文件冒泡排序
- python - 根据值调整字典
- excel - VBA根据标准将范围值与其他范围进行比较
- java - 三元运算符的意外输出
- c++ - 尽管链接正确,但未定义的升压参考