我有一个类Runner
,它实现了CoroutineScope
接口,如下所示。它有一个被挂起的函数run
。当我在这个被挂起的run
函数中使用协同例程构建器函数(launch
,async
)时,我收到以下警告
由于suspend函数的CoroutineScope接收器而导致不明确的coroutineContextRunner
类实现了一个coroutineContext属性,有人能解释一下警告消息背后的逻辑吗?
class Runner: CoroutineScope {
override private val coroutineContext = Dispatchers.IO
suspend fun run() {
val job1 = launch { delay(2000); println("launching job1") }
val job2 = launch { delay(2000); println("launching job2") }
listOf(job1, job2).forEach { it.join() }
}
}
4条答案
按热度按时间s3fp2yjn1#
由于suspend修饰符,它是不明确的。您的
run()
函数将从另一个courroutineScope调用。因此,它内部的launch
构建器可以启动一个协程或在现有协程内挂起。这就是不明确之处。您可以通过删除suspend修饰符来修复它:zmeyuzjn2#
您需要明确声明
run()
使用Runner的coroutineContext,这将消除歧义或者,如果添加了一个参数,则可以使用调用run的上下文,例如
bybem2ql3#
尽量避免在协程作用域类或函数中挂起函数,除非它会抛出上述警告
到
9bfwbjaz4#
我相信实现您所要做的事情的正确方法是使用
corotineScope
函数,而不是实现CoroutineScope
:如果您真的想使用IO分配器(在这个特定的示例中似乎没有必要),可以改用
withContext
:原始代码和大多数答案的代码可能会以意想不到的方式运行。使用具有调度程序但没有作业的上下文实现协同程序作用域将导致其行为类似于
GlobalScope
,由于某种原因,它被标记为一个微妙的API,破坏了结构化并发。