Sobes.tech
Middle

Корутинада кандайча иш болот, эгерде ката чыкса?

sobes.tech AI

AIден жооп

Корутина ичинде чыккан кырдаалда, кырдаалдын түрүнө (жана dispatcher/контексттин орнотууларына) жараша, аны кантип иштетүү керектиги аныкталат.

  • Бекемделбеген кырдаал: Эгер кырдаал корутина ичинде кармалбаса, ал корутиндердин хиерархиясы аркылуу эң жакын Job (же CoroutineScope) чейин жогору көтөрүлөт. Анын жүрүм-туруму Jobтин түрүнө жараша болот:

    • Job: Төлөмдө, эгерде балдар корутинада кырдаал пайда болсо, ата-эненин Jobи токтотулат, бул анын калган балдар корутиндерин да токтотот. Кырдаал жогору көтөрүлөт.
    • SupervisorJob: SupervisorJob кырдаал пайда болгондо токтотулбайт. Тек гана кырдаал чыккан корутина токтотулат. Бул бир баланын токтотулушу башка балдарга таасир этпеши керек болгон учурда пайдалуу.
    • CoroutineScope негизги: Эгер кырдаал CoroutineScope негизине (мисалы, GlobalScope же CoroutineScope аркылуу түзүлгөн Jobсиз scope) жетсе, ал CoroutineExceptionHandler глобалдык иштетүүчүгө өткөрүлөт. Төлөмдө, эгер иштетүүчү катталбаса, кырдаал System.errке жазылат.
  • Кармалган кырдаал: Эгер кырдаал try-catch блогу аркылуу корутина ичинде кармалса, ал жергиликтүү иштетилет жана корутина catch блогунан кийин уланат, эгер мүмкүн болсо. Кырдаал жогору көтөрүлбөйт.

  • Токтотуу менен байланышкан кырдаалдар (мисалы, CancellationException): Бул кырдаалдар өзгөчө. Алар корутиндердин токтотуу механизми үчүн колдонулат жана көбүнчө иштетүүчүлөр тарабынан көз жаздымда калтырылат. Алар Jobтин фаталдуу каталыгына алып келбейт.

  • async ичинде кырдаалдар: async аркылуу ишке киргизилген корутина өзүнүн Deferred объектине кырдаалды жайгаштырат. Кырдаал Deferred.await() чакырылганда гана өткөрүлөт. Башка учурда, ал "жашырын" калат.

import kotlinx.coroutines.*

fun main() = runBlocking {
    val scope = CoroutineScope(SupervisorJob())

    scope.launch {
        try {
            println("Корутина 1 башталды")
            delay(100)
            throw RuntimeException("Корутина 1 ичинде ката чыкты")
        } catch (e: Exception) {
            println("Корутина 1 ичинде кармалган кырдаал: ${e.message}")
        }
    }

    scope.launch {
        println("Корутина 2 башталды")
        delay(500)
        println("Корутина 2 аяктады")
    }

    delay(1000) // Натыйжаны көрүү үчүн күтүп жатабыз
    scope.cancel() // scopeти токтотуу
}

Бул мисалда, Корутина 1 ичиндеги кырдаал кармалган жана Корутина 2 ишин улантат, анткени SupervisorJob колдонулган. Эгер Job колдонулса, анда Корутина 1 ичиндеги кырдаал Корутина 2нин токтотулушуна алып келет.