Как запустить сопрограмму Kotlin в режиме «приостановить веселье», в котором используется текущий родительский Scope? - PullRequest
0 голосов
/ 20 декабря 2018

Как я могу запустить сопрограмму из функции приостановки и использовать текущую область?(чтобы область действия не заканчивалась до тех пор, пока не закончится запущенная сопрограмма)

Я хотел бы написать что-то вроде следующего:

import kotlinx.coroutines.*

fun main() = runBlocking { // this: CoroutineScope
    go()
}

suspend fun go() {
    launch {
        println("go!")
    }
}

Но здесь есть синтаксическая ошибка: "Неразрешенная ссылка: запуск ".Кажется, launch должен быть запущен одним из следующих способов -

GlobalScope.launch {
    println("Go!")
}

Или

runBlocking {
    launch {
        println("Go!")
    }
}

Или

withContext(Dispatchers.Default) {
    launch {
        println("Go!")
    }
}

Или

coroutineScope {
    launch {
        println("Go!")
    }
}

Ни одна из этих альтернатив не делает то, что мне нужно.Либо код «блокирует», а не «порождает», либо он порождается, но родительская область не будет ждать его завершения, пока не закончится сама родительская область.

Мне нужно, чтобы он «порождался» (запускался) втекущая родительская область сопрограмм и эта родительская область должны ожидать завершения порожденной сопрограммы, прежде чем она завершится.

Я ожидал, что простой launch внутри suspend fun будет действительным и будет использовать свою родительскую область действия.

Я использую Kotlin 1.3 и cotlinx-coroutines-core:1.0.1.

Ответы [ 2 ]

0 голосов
/ 20 декабря 2018

Вы должны сделать функцию go функцией расширения CoroutineScope:

fun main() = runBlocking {
    go()
    go()
    go()
    println("End")
}

fun CoroutineScope.go() = launch {
    println("go!")
}

Прочтите эту статью , чтобы понять, почему начинать вsuspend выполняет другие сопрограммы без создания новой coroutineScope{}.

Соглашение таково: в suspend функции вызывают другие suspend функции и создают новую CoroutineScope, если вам нужно начать параллельносопрограммы.В результате сопрограмма вернется только после завершения всех вновь запущенных сопрограмм (структурированный параллелизм).

С другой стороны, если вам нужно запустить новые сопрограммы, не зная области действия, вы создаете расширенияфункция CoroutineScope, которая сама по себе не suspendable.Теперь вызывающая сторона может решить, какую область следует использовать.

0 голосов
/ 20 декабря 2018

Я считаю, что нашел решение, которое with(CoroutineScope(coroutineContext).Следующий пример иллюстрирует это -

import kotlinx.coroutines.*

fun main() = runBlocking {
    go()
    go()
    go()
    println("End")
}

suspend fun go() {
//  GlobalScope.launch {                     // spawns, but doesn't use parent scope
//  runBlocking {                            // blocks
//  withContext(Dispatchers.Default) {       // blocks
//  coroutineScope {                         // blocks
    with(CoroutineScope(coroutineContext)) { // spawns and uses parent scope!
        launch {
            delay(2000L)
            println("Go!")
        }
    }
}

Однако Рене опубликовал гораздо лучшее решение выше.

...