Вывод на консоль ожидает завершения CoroutineScope {} тела

#kotlin #kotlin-coroutines

#kotlin #котлин-сопрограммы

Вопрос:

есть пример:

 import kotlinx.coroutines.*
 
fun main() = runBlocking { // this: CoroutineScope
 
    launch {
        delay(200L)
        println("Task from runBlocking")
    }
 
    coroutineScope { // Creates a coroutine scope
        launch {
            delay(500L)
            println("Task from nested launch")
        }
 
        delay(100L)
        println("Task from coroutine scope") // This line will be printed before the nested launch
    }
 
    println("Coroutine scope is over") // This line is not printed until the nested launch completes
}
 

Результат таков:

Задача из области сопрограммы

Задача из-за блокировки выполнения

Задача из вложенного запуска

Область действия сопрограммы завершена

Можете ли вы объяснить, почему вывод в строке 20 (println(«Область действия сопрограммы завершена»)) происходит в самом конце, после завершения тела CoroutineScope{}?

Я просто подумал, что строка 20 выполняется в основном потоке, и что launch{} и CoroutineScope{} создали сопрограммы, работающие параллельно. Поэтому я ожидал, что

Область действия сопрограммы завершена

будет отображаться в самом начале.

Ответ №1:

В документации к функции coroutineScope говорится, что она приостанавливается и не возвращается, пока не будут завершены все ее дочерние сопрограммы:

Эта функция возвращается, как только данный блок и все его дочерние сопрограммы завершены.

Если вы создадите дочернюю область и вызовете для нее launch , поведение будет таким, как вы ожидали:

 fun main() = runBlocking {

    launch {
        delay(200L)
        println("Task from runBlocking")
    }

    val scope = CoroutineScope(coroutineContext)
    scope.launch {
        launch {
            delay(500L)
            println("Task from nested launch")
        }

        delay(100L)
        println("Task from coroutine scope")
    }

    println("Coroutine scope is over")
}
 

выводит

 Coroutine scope is over
Task from coroutine scope
Task from runBlocking
Task from nested launch
 

Комментарии:

1. Почему бы не написать launch { ... } вместо CoroutineScope(coroutineContext).launch { ... } ?

2. Просто показываю разницу между CoroutineScope() и coroutineScope поскольку OP, похоже, изучает, как создать независимый CoroutineScope.