Kotlin сопрограмма - множественная ошибка вызывает cra sh до достижения блока catch - PullRequest
0 голосов
/ 03 марта 2020

У меня проблема: когда мой код выдает несколько исключений в сопрограмме fn (в фоновом режиме), тогда основное приложение создает sh перед выполнением блока catch в фоновом режиме, но после этого выполняет блок catch. Как это можно исправить? Код работает нормально, если выбрасывает ошибку 1, но cra sh, если выдает многократную ошибку.

Ожидание: перехват первой ошибки и остановка выполнения в runBlocking без cra sh основное приложение.

Сообщение об ошибке:

E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-8
    Process: ..., PID: 9260
    RuntimeException: my error
        at MyBackgroundService ...
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:234)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:742)

Следующий код является очень упрощенной версией моего кода, которая представляла, как выглядит мой структурированный параллелизм:

class MyBackgroundService : IntentService("..."), CoroutineScope {

    private var cJob: Job = Job()

    override val coroutineContext: CoroutineContext
        get() = Dispatchers.IO + cJob

    override fun onHandleIntent(intent: Intent?) {
        /*...*/
        try {
            runBlocking {
                fn1();
                fn2();
            }
        } catch(e: RuntimeException) {
            //before execution reach this the main app crashed with my custom error
            //after that the app execute the catch block code and other coroutine fn still running in fn2
        }
    }

    private suspend fun fn1() {
        withContext(coroutineContext) {
             /*...*/
        }
    }

    private suspend fun fn2() {
        withContext(coroutineContext) {
             /*...*/
             fn3()
             /*other similar fn calls*/
             /*after throw exception in fn3 the other coroutine functions still running */
        }
    }

    private suspend fun fn3() {
        launch {
            fn4() 
        }
    }

    private suspend fun fn4() {
        coroutineScope {
            launch {
               /*...*/
               fn5()
            }
        }
    }

    fun CoroutineScope.fn5() {
        for (/*...*/) {
             launch {
                 fn6()
             }
        }
    }

    private suspend fun fn6() {
        coroutineScope {
            launch {
               /*...*/
               if (/*..*/) {
                   throw RuntimeException("my error") //this called multiple time because of for
               }
            }
        }
    }
}


1 Ответ

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

Хорошо, я нашел проблему: двусмысленный сопрограммный код в fn3, поэтому исправление:

private suspend fun fn3() {
    coroutineScope {
        launch {
            fn4() 
        }
    }
}
...