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")
}
Здесь вы используете глобальную область сопрограмм, поэтому вы не получаете автоматического отмены. Если вы хотите позаботиться об этом, замените его чем-нибудь другим.