Coroutines and exceptions: things to know

栏目: IT技术 · 发布时间: 5年前

内容简介:Coroutines are an awesome way to write async code. Your code looks almost similar to the sync equivalent but it's not blocking.When everything goes according to plan, no need to worry about weird behavior from coroutines. What happens though when things do

Coroutines are an awesome way to write async code. Your code looks almost similar to the sync equivalent but it's not blocking.

When everything goes according to plan, no need to worry about weird behavior from coroutines. What happens though when things don't go according to plan, i.e. exceptions are thrown? Can those exceptions be caught like regular sync code?

The answer depends on the coroutine builder used.

async

The async coroutine builder works as you would expect, i.e. similar to how sync code handles exceptions. They rely on the user to handle the exception, otherwise, it's thrown as unhandled.

val deferred = GlobalScope.async {
    throw ArithmeticException()
}
    
try {
    deferred.await()
} catch (e: ArithmeticException) {
    // Exception caught
}

launch

On the other hand, launch coroutine builder treats exceptions as unhandled. These can be caught by  Java's Thread.uncaughtExceptionHandler .

try {
    GlobalScope.launch {
        throw ArithmeticException()
    }
} catch (e: ArithmeticException) {
    // Exception will *not* be caught
}

Of course, relying on Thread.uncaughtExceptionHandler is not a great idea to handle all exceptions across your app.

Coroutine builders accept an additional CoroutineExceptionHandler parameter for these cases.

val handler = CoroutineExceptionHandler { _, exception -> 
    // Exception caught
}

GlobalScope.launch(handler) {
    throw ArithmeticException()
}

Child-parent exception relationship

Speaking of exceptions, we should note the default behavior of coroutines when they encounter an exception.

A child coroutine encountering an exception will cancel itself and its parent coroutine with that exception.  

val handler = CoroutineExceptionHandler { _, exception -> 
    // ArithmeticException will be caught.
    //
    // 1st child will not complete because parent is cancelled (i.e. and
    // children as well)
}

GlobalScope.launch(handler) {
    launch { // 1st child
        delay(Long.MAX_VALUE)
        print("This will not be printed")
    }
    launch { // 2nd child
        throw ArithmeticException()
    }
}

A small detail, but the original exception will be handled by the parent after all its children coroutines terminate. So, if the 2nd child was running with NonCancellable context, the handler would be called after the completion of the 2nd child.

val handler = CoroutineExceptionHandler { _, exception -> 
    // 1st child complete, then ArithmeticException will be caught.
}

GlobalScope.launch(handler) {
    launch(NonCancellable) { // 1st child
        delay(Long.MAX_VALUE)
        print("This will be printed")
    }
    launch { // 2nd child
        throw ArithmeticException()
    }
}

A special exception

The CancellationException is treated differently than the rest of the exceptions. It's ignored by the exception handlers and does not cause the cancellation of the parent coroutine.

launch {
    val child = launch {
        delay(Long.MAX_VALUE)
    }
    child.join()
    child.cancel() // Parent is not cancelled, 
                   // although child is throwing a CancellationExeption
    print("Hello from parent")
}

Multiple exceptions

In case multiple children throw exceptions, the first one wins. There is a way to catch additional exceptions that might have been thrown after the first one.

val handler = CoroutineExceptionHandler { _, exception -> 
    // ArithmeticException will be caught (from 2nd child).
    //
    // IOException can be accessed using exception.suppressed (from 1st child) 
}

GlobalScope.launch(handler) {
    launch { // 1st child
        try {
            delay(Long.MAX_VALUE)
        }
        finally {
            throw IOException()
        }
    }
    launch { // 2nd child
        throw ArithmeticException()
    }
}

Hopefully, the relationship between coroutines and exception is a bit clearer now. You can always refer to the excellent Kotlin docs . Happy throwing!


以上所述就是小编给大家介绍的《Coroutines and exceptions: things to know》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

奥美的数字营销观点

奥美的数字营销观点

[美] 肯特·沃泰姆、[美] 伊恩·芬威克 / 台湾奥美互动营销公司 / 中信出版社 / 2009-6 / 45.00元

目前,媒体的数字化给营销人带来了重大影响。新媒体世界具有多重特性,它赋予企业大量机会,同时也带来挑战。营销人有了数量空前的方式来与消费者互动。然而,许多人面对变革的速度感到压力巨大,而且不知道该如何完全发挥这些新选择所带来的优势。 本书为读者提供了如何运用主要数字媒体渠道的方法;随附了领先的营销人如何在工作中有效运用这些渠道的最佳案例;提供了数字营销的十二个基本原则;协助数字营销人了解什么是......一起来看看 《奥美的数字营销观点》 这本书的介绍吧!

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具