概述
有时我们需要关闭一些线程,我们不能只是杀死线程,因为我们需要释放资源并关闭连接。
协程提供了一个简单的撤消机制来解决此类问题以及长时间运行的操作或内存泄漏的问题。
取消Jobs
让我们使用工厂函数创建一个对象:Job()
suspend fun main() = coroutineScope {
val job = Job()
}
此 Job 对象表示正在运行的协程。我们不需要其结果的协程可以通过调用该函数随时取消:job.cancel()
suspend fun main() = coroutineScope {
val job = Job()
launch(job) {
repeat(1000) { i ->
delay(50)
println("$i")
}
}
job.cancel()
}
协程将被取消,而无需等待其实际完成。再次调用取消不会执行任何操作。
取消协程是完全线程安全且非阻塞的。
如果我们需要等待 Job 完成,我们可以使用:job.join()
suspend fun main() = coroutineScope {
val job = Job()
launch(job) {
repeat(1000) { i ->
delay(50)
println("$i")
}
}
delay(500)
job.cancel()
job.join()
println("Cancelled")
}
我们也可以将这两个调用组合到函数中。job.cancelAndJoin()
异常处理
如果job被取消,将引发 a。我们可以用尝试捕捉来抓住它:CancellationException
suspend fun main() = coroutineScope {
val job = Job()
launch(job) {
try {
repeat(1000) { i ->
delay(50)
println("$i")
}
} catch (e: CancellationException) {
println(e)
} finally {
println("Finally")
}
}
delay(500)
job.cancelAndJoin()
println("Cancelled")
}
СancelationException
是处理协程执行取消的特殊例外。
我们可以为当前协程执行上下文中发生的所有未处理的异常定义行为。为此,可以使用 ,它是任何异常的侦听器。CoroutineExceptionHandler
CoroutineExceptionHandler { coroutineContext, throwable ->
println(throwable)
}
我们可以通过这种方式从任何线程中捕获异常,并为所有这些线程定义默认行为。 在发生错误后最后调用。CoroutineExceptionHandler
结论
协程中的取消易于使用,并且对于应用程序的性能非常重要。我们可以在协程中使用取消来简化资源清理,或者可能使用某种形式的错误日志记录。