Обрабатывает ли прицел исключение / отказ молча под капотом? - PullRequest
4 голосов
/ 12 марта 2020

У меня есть следующий фрагмент для тестирования:

fun main() {

   val myScope = CoroutineScope(Dispatchers.Default) + Job()

   myScope.launch {

       val job = async {
           delay(1000)
           throw RuntimeException("shiiiet")
       }

       try {
           job.await()
       } catch (ret: RuntimeException){
           throw RuntimeException("yooo!")
       }
   }

    try {
        Thread.sleep(5000)
    } catch(e: Exception){

    }

    println("wohoooo!") 
}

Я думал, что поток никогда не достигнет последнего "ухо!" линия, но я был неправ. Я вижу, что это напечатано на экране. Причина, по которой я думал, что launch будет распространять исключение в родительскую область, и, поскольку родительская область не обрабатывает его, к моменту достижения оператора print она создаст sh JVM.

Это потому, что родительская область была отменена после того, как произошел сбой дочернего элемента, получено исключение CancellationException, и оно было проигнорировано?

1 Ответ

0 голосов
/ 13 марта 2020

В вашем примере вы опробовали несколько подходов throw и catch.

async работает должным образом - когда вы await для него, вы можете поймать исключение. Но если вы launch подпрограмма, по умолчанию Thread.uncaughtExceptionHandler просто выводит результат на консоль.

Даже если вы выполните

myScope.launch {
    ....
}.invokeOnCompletion { e -> println("Exception: $e") }

, вы все равно получите результат на консоли .

Объясняются правила распространения и различные типы вызовов для обработки исключений здесь .

Пример того, как перехватить исключение в "основной" команде -программа:

fun main() = runBlocking {
    try {
        GlobalScope.launch {
            delay(10)
            throw Exception("You don't catch me in main.")
        }
        launch {
            delay(10)
            throw Exception("You catch me in main.")
        }
        delay(100)
        println("Never reached.")
    } catch(e: Exception) {
        println("Caught in main: ${e.cause}")
    }
    println("The end")
}
...