When your objective is to start a coroutine that doesn't return a result, you should use launch(). It's designed for fire-and-forget scenarios where you only want to be notified if the computation fails, and it still provides you with a function to cancel it if needed. Consider this example:
fun main(args: Array<String>) = runBlocking { val task = launch { doSomething() } task.join() println("completed") }
Here, doSomething() throws an exception:
fun doSomething() { throw UnsupportedOperationException("Can't do") }
The exception will be printed to the stack as expected, but notice that the execution was not interrupted and the application finished the execution of main():
As we will see in chapter 3, Life Cycle and Error Handling, the default behavior for uncaught exceptions is defined per platform, but can be overwritten.