CoroutineScope 取消监听
CoroutineScope cancel listener
我正在 class 中使用 Scope 执行一些工作:
class MyClass(val scope: CoroutineScope) {
private val state: StateFlow<Int> = someFlow()
.shareIn(scope, started = SharingStared.Eagerly, initialValue = 0)
fun save() {
scope.launch {
save(state.value)
}
}
}
现在我想在作用域被取消时进行清理。做这个的最好方式是什么?我可以想出这个,但这听起来不太稳定。
init {
scope.launch {
try { delay(10000000000000) }
finally { withContext(Noncancellable) { save(state.value) } }
}
}
编辑:我修改了我的代码片段以更好地反映我正在做的事情。 state
Flow 每秒更新几次,当我调用 save()
方法时,我想将状态保存到磁盘(所以我不想每次状态更改时都这样做)。
接下来,我想在范围被取消时(即最后)保存状态。这就是我遇到问题的地方。
您可以使用异常处理程序
// Destroy service when completed or in case of an error.
val handler = CoroutineExceptionHandler { _, exception ->
Log.e("CoroutineExceptionHandler Error", exception.message!!)
stopSelf(startId)
}
然后你可以使用这个Handler作为
scope.launch(handler){
// do stuff
}
handler
将被调用 仅当抛出异常时
据我所知,CoroutineScope
上没有这种“onCancellation”机制。
一般情况下,清理可以在执行需要清理的代码时就地“准备”。例如,使用带有 use { ... }
的输入流或使用 finally
块关闭资源。
这将在取消(或任何其他失败,顺便说一句)时自动兑现,因为范围的取消只会在 运行 协程中生成 CancellationException
s。
现在,有时(如您的情况)您有更复杂的需求,在那种情况下,我会说范围的取消只是在某种生命周期结束时发生的一件事,而您可以在取消范围的同一位置进行所需的清理。
如果你真的想使用像你当前的并行协程这样的解决方法,你可以使用 awaitCancellation 而不是巨大的延迟:
init {
scope.launch {
try { awaitCancellation() }
finally { withContext(Noncancellable) { save(state.value) } }
}
}
但我还是觉得它不太吸引人。
我正在 class 中使用 Scope 执行一些工作:
class MyClass(val scope: CoroutineScope) {
private val state: StateFlow<Int> = someFlow()
.shareIn(scope, started = SharingStared.Eagerly, initialValue = 0)
fun save() {
scope.launch {
save(state.value)
}
}
}
现在我想在作用域被取消时进行清理。做这个的最好方式是什么?我可以想出这个,但这听起来不太稳定。
init {
scope.launch {
try { delay(10000000000000) }
finally { withContext(Noncancellable) { save(state.value) } }
}
}
编辑:我修改了我的代码片段以更好地反映我正在做的事情。 state
Flow 每秒更新几次,当我调用 save()
方法时,我想将状态保存到磁盘(所以我不想每次状态更改时都这样做)。
接下来,我想在范围被取消时(即最后)保存状态。这就是我遇到问题的地方。
您可以使用异常处理程序
// Destroy service when completed or in case of an error.
val handler = CoroutineExceptionHandler { _, exception ->
Log.e("CoroutineExceptionHandler Error", exception.message!!)
stopSelf(startId)
}
然后你可以使用这个Handler作为
scope.launch(handler){
// do stuff
}
handler
将被调用 仅当抛出异常时
据我所知,CoroutineScope
上没有这种“onCancellation”机制。
一般情况下,清理可以在执行需要清理的代码时就地“准备”。例如,使用带有 use { ... }
的输入流或使用 finally
块关闭资源。
这将在取消(或任何其他失败,顺便说一句)时自动兑现,因为范围的取消只会在 运行 协程中生成 CancellationException
s。
现在,有时(如您的情况)您有更复杂的需求,在那种情况下,我会说范围的取消只是在某种生命周期结束时发生的一件事,而您可以在取消范围的同一位置进行所需的清理。
如果你真的想使用像你当前的并行协程这样的解决方法,你可以使用 awaitCancellation 而不是巨大的延迟:
init {
scope.launch {
try { awaitCancellation() }
finally { withContext(Noncancellable) { save(state.value) } }
}
}
但我还是觉得它不太吸引人。