Kotlin: вернуть карту асинхронности (start = CoroutineStart.LAZY)

Я хотел бы вернуть карту лениво запущенных сопрограмм и использовать их (запуск / отмена) в другой функции.

Проблема в том, что функция getMap() в следующих зависаниях. Почему это так и можно ли вернуть такую ​​карту из функции?

import kotlinx.coroutines.*

suspend fun getMap(): LinkedHashMap<String, Deferred<Any>> {
    return withContext(Dispatchers.Default) {
        val map = linkedMapOf<String, Deferred<Any>>()
        map["1"] = async(start = CoroutineStart.LAZY) { 1 }
        map["2"] = async(start = CoroutineStart.LAZY) { 2 }
        map;
    }
}

fun main() {
    runBlocking {
        val map = getMap()
        println("not happening")
    }
}

1 ответ

Решение

withContext не завершается, пока не будут завершены все сопрограммы, запущенные в нем. Вы можете упростить свой случай до этого:

fun main() {
    runBlocking {
        withContext(Dispatchers.Default) {
            launch(start = CoroutineStart.LAZY) { 1 }
        }
        println("not happening")
    }
}

Это также не завершено. Причина в том, что вы использовали это, что вы использовали withContext ненадо. Ваш getMap() нет причин быть suspend fun,

Что тебе нужно вместо withContext устанавливает область сопрограмм для этих async звонки. Например, это будет работать:

fun getMap(): Map<String, Deferred<Any>> =
        linkedMapOf<String, Deferred<Any>>().also { map ->
            with(GlobalScope) {
                map["1"] = async(start = CoroutineStart.LAZY) { 1 }
                map["2"] = async(start = CoroutineStart.LAZY) { 2 }
            }
        }

fun main() {
    val map = getMap()
    println("now it's happening")
}

Здесь вы используете глобальную область сопрограмм, поэтому вы не получаете автоматического отмены. Если вы хотите позаботиться об этом, замените его чем-нибудь другим.

Другие вопросы по тегам