Kotlin:异步返回地图(开始= CoroutineStart.LAZY)

时间:2018-11-28 14:03:25

标签: kotlin kotlin-coroutines

我想返回懒惰启动的协程的地图,并在另一个函数中使用它们(启动/取消)。

问题是以下挂起的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 个答案:

答案 0 :(得分:3)

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")
}

在这里,您正在使用全局协程范围,因此不会得到任何自动取消。如果您要解决此问题,请换成其他东西。