Reputation: 3297
I have a class that implements CoroutineScope, and it has a function run
, which has one parameter for me to test if I want to throw an exception.
In the example, I found the code block inside the launch
in the second run
call is not actually executed. Is this intended behavior? It took me some time to find out the problem in my original code because the log does not say anything until I wrote the sample code to test. If that is intended, what is the best practice to fix the problem? What I want to achieve is to reuse the run
function, and be able to catch the exception inside that function.
package coroutine.exceptions
import kotlinx.coroutines.*
fun log(msg: String) = println("$msg (${Thread.currentThread().name})")
val exceptionHandler = CoroutineExceptionHandler { _, e ->
log(e.localizedMessage)
}
fun main() = runBlocking {
val test1 = TestReuseCoroutineAfterException("test1")
test1.run(true)
delay(2000)
test1.run(false)
delay(2000)
log("finished")
}
class TestReuseCoroutineAfterException(private val testName: String) :
CoroutineScope by CoroutineScope(Dispatchers.Default) {
fun run(throwException: Boolean) {
log("$testName: call - started")
launch(exceptionHandler) {
if (throwException)
throw Exception("$testName: call - throw exception")
else
log("$testName: call - done")
}
log("$testName: call - ended")
}
}
Output:
test1: call - started (main)
test1: call - ended (main)
test1: call - throw exception (DefaultDispatcher-worker-1)
test1: call - started (main)
test1: call - ended (main)
finished (main)
Process finished with exit code 0
Upvotes: 0
Views: 632
Reputation: 3890
When you create a CoroutineScope
like this:
CoroutineScope(Dispatchers.Default)
It uses Job()
as its Job, and Job()
cancels the scope if an exception was throws in child coroutine. If you don't want to cancel the whole scope if a child fails, use SupervisorJob:
CoroutineScope(Dispatchers.Default + SupervisorJob())
After this change your code prints:
test1: call - started (main)
test1: call - ended (main)
test1: call - throw exception (DefaultDispatcher-worker-1)
test1: call - started (main)
test1: call - ended (main)
test1: call - done (DefaultDispatcher-worker-2)
finished (main)
Upvotes: 4