Sobes.tech
Middle

რა ხდება კორუტინასთან, როდესაც გამონაკლისი ხდება?

sobes.tech AI

პასუხი AI-სგან

კორუტინში გამოდის გამონაკლისი, დამოკიდებულია გამონაკლისის ტიპზე (და dispatcher/კონტექსტის კონფიგურაციაზე), როგორ იქნება ის დამუშავებული.

  • არაკონტროლირებადი გამონაკლისი: თუ გამონაკლისი არ არის ჩაჭერილი კორუტინში, ის გადაეცემა ზევით კორუტინების ჰიეარარქიაში ყველაზე ახლოს მდებარე Job-ს (ან CoroutineScope-ს). ქცევა დამოკიდებულია Job-ის ტიპზე:

    • Job: სტანდარტულად, თუ დეველოპერი გამონაკლისი ხდება შვილობილი კორუტინაში, მშობელი Job გაუქმდება, რაც გამოიწვევს მის სხვა შვილობილი კორუტინების გაუქმებას. გამონაკლისი გადაეცემა ზევით.
    • SupervisorJob: SupervisorJob-ი არ გაუქმდება გამონაკლისის დროს შვილობილი კორუტინაში. მხოლოდ ის კორუტინა გაუქმდება, სადაც გამონაკლისი მოხდა. ეს სასარგებლოა, როდესაც ერთი შვილობილი დავალების გაუქმება არ უნდა ზეგავლენდეს სხვაებზე.
    • CoroutineScope-ის ძირითადი: თუ გამონაკლისი მიაღწევს CoroutineScope-ს (მაგალითად, GlobalScope ან CoroutineScope-ით შექმნილი Scope-ს გარეშე), ის გადაეცემა გლობალურ გამონაკლისების დამუშავებელს CoroutineExceptionHandler. სტანდარტულად, თუ არ არის რეგისტრირებული დამუშავებელი, გამონაკლისი იწერება System.err-ში.
  • დამჭერილი გამონაკლისი: თუ გამონაკლისი არის ჩაჭერილი try-catch ბლოკით კორუტინში, ის დამუშავდება ადგილობრივად და კორუტინა გააგრძელებს შესრულებას catch-ის შემდეგ, თუ ეს შესაძლებელია. გამონაკლისი ზევით არ გადაეცემა.

  • გამონაკლისები, დაკავშირებული გაუქმებასთან (მაგალითად, CancellationException): ეს გამონაკლისები განსაკუთრებულია. ისინი გამოიყენება კორუტინების გაუქმების მექანიზმისთვის და ჩვეულებრივ იგნორირებულია უმეტეს დამუშავებლების მიერ. ისინი არ იწვევს ფატალურ შეცდომას მშობელ Job-ში.

  • async-ში გამონაკლისები: async-ით დაწყებული კორუტინა აყენებს გამონაკლისს თავის 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-ის გაუქმებას.