从挂起的函数启动协程

Launching coroutines from a suspended function

鉴于我们有一个挂起函数,但 this 不是 CoroutineScope,我们如何启动其他协程,以便它们与运行此 suspending 的任何对象的当前范围相关联功能?

您可以在 CoroutineScope 上创建扩展函数或使用 CoroutineScope 作为参数的函数:

fun CoroutineScope.doThis() {
    launch { ... }
}

fun doThatIn(scope: CoroutineScope) {
    scope.launch { ... }
}

也可以使用coroutineScope or supervisorScope,看你的需要:

suspend fun someFun() = coroutineScope {
    launch { ... }
}

suspend fun someFun() = supervisorScope {
    launch { ... }
}

您可以只使用 withContext()coroutineScope() 来启动另一个协程:

withContext(coroutineContext) {
    launch { ... }
}

虽然第二个会覆盖上下文的 Job,但会重用上下文:

coroutineScope {
    launch { ... }
}

每个可挂起的函数都可以访问全局变量 coroutineContext,您可以将其简单地包装在 CoroutineScope 中,但这不是它的预期目的。它就在那里,所以你可以随时检查你的协程是否被取消,获取调试信息,如作业名称等。

用 Roman Elizarov 在他最近的 Medium post 中的话来说:

suspend fun doNotDoThis() {
    CoroutineScope(coroutineContext).launch {
        println("I'm confused")
    }
}

Do not do this!

可挂起的函数不应触发可能在它之后继续的并发工作 returns。它应该只使用并发来实现任务的并行分解,这意味着它将等待所有子协程完成。

您应该决定使用作为 CoroutineScope 接收者的普通函数(表示启动并发工作的意图) 使用等待的可挂起函数完成它发起的所有工作。

因此,如果您想要并行分解,请使用 coroutineScope 或者可能是 supervisorScope 块:

coroutineScope {
    launch { 
        // ... task to run in the background
    }
    // ... more work while the launched task runs in parallel
}
// All work done by the time we reach this line

coroutineScope 是一个可挂起的函数,直到它启动的所有协程都完成后才会完成。