如何等待并正确 return 来自异步协程的值

How to wait and properly return value from async coroutine

我通过单击按钮调用 function(非暂停)。我想 运行 使用 async 协程和 return 最后计算值在 function 中循环。

我的代码:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    btnCount.setOnClickListener {

        var result = GlobalScope.async { dummyFoo() }
        runBlocking {
            Toast.makeText(this@MainActivity, result.await().toString(), Toast.LENGTH_LONG).show()
        }
    }
}

private fun dummyFoo() : Int {
    var result : Int = 0
    val waitFor = CoroutineScope(Dispatchers.IO).async {
        for (i in 1..20000) {
            result++
        }
        return@async result
    }

    return result
}

输出:

我在 Toast 中得到 0

我想要 20000 Toast

如何让我的代码等到循环完成和结果变为 20000 并输出它?

不确定我是否明白这样做的目的,但如果这是您想要的,请将 Dispatchers.IO 替换为 Dispatchers.Unconfined

你应该在 dummyFoo() 中使用 await

private suspend fun dummyFoo() : Int {
    var result : Int = 0
    val waitFor = CoroutineScope(Dispatchers.IO).async {
        for (i in 1..20000) {
            result++
        }
        return@async result
    }
    waitFor.await()
    return result
}

您似乎想在 GUI 线程之外启动一个 CPU 密集型任务,然后在 GUI 中显示结果。这是协程的一个基本用例,解决方法如下:

btnCount.setOnClickListener {
    GlobalScope.launch(Dispatchers.Main) {
        val result = withContext(Dispatchers.Default) {
            dummyFoo()
        }
        Toast.makeText(this@MainActivity, result.toString(), Toast.LENGTH_LONG).show()
    }
}

这伴随着通常的警告,即您不应在全局范围内启动协程,而应为相关 activity 创建一个范围。否则,即使用户离开您的应用,这些后台任务也会占用 CPU。