工作管理器协程工作线程的流取消



我有以下设置:

override suspend fun doWork(): Result = coroutineScope {
flowOfEvents
.onEach(eventChannel::send)
.launchIn(this)  
if (isQueueEmpty()) return@coroutineScope Result.success()
... 
}

我看到的是:当isQueueEmpty()为真时,我返回Result.success(),我希望flowOfEvents...launchIn(this)流也会被处理/取消,但我一直从该流接收事件。

我做错什么了吗?

launchIn(this)捕获Job并在每个返回语句之前显式调用job.cancel()可以工作,但感觉没有必要/错误。

经过一番研究,发现这是Kotlin协同程序的行为,与WorkManager完全无关。

  • Flow<Event>是一项永无止境的工作
  • 根据定义,父协同程序等待子协同程序完成

考虑到这两点,现在很明显,为什么我从父协同程序返回后仍会收到Events。

解决方案:在从父协同程序返回之前调用coroutineContext[Job]?.cancelChildren()

override suspend fun doWork(): Result = coroutineScope {
flowOfEvents
.onEach(eventChannel::send)
.launchIn(this)  
if (isQueueEmpty()) {
coroutineContext[Job]?.cancelChildren()
return@coroutineScope Result.success()
}
... 
}

注意:调用父级的cancel()会抛出一个CancellationException,在WorkManager的上下文中,这意味着Worker#doWork方法实际上会导致作业失败

最新更新