【问题标题】:Why CoroutineExceptionHandler didn't catch/handle my exception?为什么 CoroutineExceptionHandler 没有捕获/处理我的异常?
【发布时间】:2018-10-15 22:13:18
【问题描述】:

在这段代码中为什么handler 只打印JobCancellationException 而不是SocketException 的堆栈跟踪? launch 内部的 foo 函数肯定会抛出 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)
}

【问题讨论】:

  • 我认为 runBlocking 不会处理 CoroutineExceptionHandler

标签: kotlin kotlinx.coroutines


【解决方案1】:

我无法告诉你为什么CoroutineExceptionHandler 没有捕捉到launch 中抛出的异常。但我可以告诉你两件事 -

  1. 我验证了您发现的行为 - 您是正确的,没有捕获到异常。
  2. 通过实验,我学会了如何捕捉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

关键要点是,如果您在自定义 CoroutineScope 上调用 launch,则当在 @987654332 中引发异常时,将执行直接提供给 CoroutineScope 构造函数或 launch 的任何 CoroutineExceptionHandler @ed 协程。

希望有帮助!!

更新

我发现了为什么没有捕获到异常。看我的回答here

【讨论】:

    猜你喜欢
    • 2010-11-16
    • 2012-01-22
    • 2020-08-18
    • 1970-01-01
    • 2020-11-16
    • 2010-11-25
    • 2012-02-24
    相关资源
    最近更新 更多