协程中的NonCancellable
NonCancellable其实是一个特殊的Job,看它的注释:
A non-cancelable job that is always active. It is designed for withContext function to prevent cancellation of code blocks that need to be executed without cancellation.
(设计目的是让withContext块在取消时也可以运行)
Use it like this:
withContext(NonCancellable) {
// this code will not be cancelled
}WARNING: This object is not designed to be used with
launch, async
, and other coroutine builders. if you write launch(NonCancellable) { … } then not only the newly launched job will not be cancelled when the parent is cancelled, the whole parent-child relation between parent and child is severed. The parent will not wait for the child’s completion, nor will be cancelled when the child crashed.换言之,不建议在launch async上用——因为它破坏了结构化并发
正常来说,
- 在进入withContext块之前,如果已经cancel了,那么不会进入,
- 如果已经进入了,然后被cancel,在块中有
delay
这种可取消挂起函数,会抛出cancellationException
结束withContext
块 - 如果在
withContext
结束返回值的时候检测到取消,会丢弃返回值并抛出cancellationException
那么NonCancellable可以帮助它:
- 如果已经cancel了,那么依然进入
- 如果已经进入了,然后被cancel,在块中有
delay
这种可取消挂起函数,忽略 - 如果在
withContext
结束返回值的时候检测到取消,忽略
换言之,不参与结构化并发。
其实不用NonCancellable
,自己显示定义一个Job()
也可以做到。
1 | fun main() = runBlocking { |