WorkManager CoroutineWorker 的流取消
WorkManager CoroutineWorker's stream cancellation
我有以下设置:
override suspend fun doWork(): Result = coroutineScope {
flowOfEvents
.onEach(eventChannel::send)
.launchIn(this)
if (isQueueEmpty()) return@coroutineScope Result.success()
...
}
我看到的是以下内容:当 isQueueEmpty()
为真时,我 return Result.success()
并且我希望 flowOfEvents...launchIn(this)
流为 disposed/cancelled 也一样,但我不断从该流接收事件。
我是不是做错了什么?
从 launchIn(this)
捕获作业并在每个 return 语句工作之前显式调用 job.cancel()
,但感觉 unnecessary/wrong.
经过一些研究,很明显这是 Kotlin 协程行为,与 WorkManager
完全无关。
- 听
Flow<Event>
是一项 never-ending 的工作
- 根据定义,父协程等待子协程完成
鉴于这两点,现在很明显为什么我从父协程返回后仍然收到 Event
s。
解决方法:在父协程返回前调用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
方法实际上会产生结果在失败的工作中。
我有以下设置:
override suspend fun doWork(): Result = coroutineScope {
flowOfEvents
.onEach(eventChannel::send)
.launchIn(this)
if (isQueueEmpty()) return@coroutineScope Result.success()
...
}
我看到的是以下内容:当 isQueueEmpty()
为真时,我 return Result.success()
并且我希望 flowOfEvents...launchIn(this)
流为 disposed/cancelled 也一样,但我不断从该流接收事件。
我是不是做错了什么?
从 launchIn(this)
捕获作业并在每个 return 语句工作之前显式调用 job.cancel()
,但感觉 unnecessary/wrong.
经过一些研究,很明显这是 Kotlin 协程行为,与 WorkManager
完全无关。
- 听
Flow<Event>
是一项 never-ending 的工作 - 根据定义,父协程等待子协程完成
鉴于这两点,现在很明显为什么我从父协程返回后仍然收到 Event
s。
解决方法:在父协程返回前调用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
方法实际上会产生结果在失败的工作中。