public suspend inline fun <T : Closeable?, R> T.useCancellably(
crossinline block: (T) -> R
): R = suspendCancellableCoroutine { cont ->
cont.invokeOnCancellation { this?.close() }
cont.resume(use(block))
}
确保这适用于你正在使用的 API !
现在阻塞的 accept
调用被 useCancellably
包裹,该协程会在超时触发的时候失败。
runBlocking(Dispatchers.IO) {
withTimeout(1000) {
val socket = ServerSocket(42)
// 抛出 SocketException: socket closed
异常。好极了!
socket.useCancellably { it.accept() }
}
}
成功!
如果你不支持取消怎么办?以下是你需要注意的事项:
- 如果你使用协程封装类中的任何属性或方法,即使取消了协程也会存在泄漏。如果你认为你正在
onDestroy
中清理资源,这尤其重要。解决方法: 将协同程序移动到ViewModel
或其他上下文无关的类中并订阅它的处理结果。 - 确保使用
Dispatchers.IO
来处理阻塞操作,因为这可以让 Kotlin 留出一些线程来进行无限等待。 - 尽可能使用
suspendCance