繁体   English   中英

如何中断 Thread.sleep。 备择方案?

[英]How to interrupt Thread.sleep. Alternatives?

我已经在 OperationQueue 上实现了一个操作。

override func main() {
    super.main()
    if isCancelled {
        return
    }
    if member.memberType == .timed {
        triggerRestEvent(duration: member.restDuration)
    }
    if isCancelled {
        triggerEndEvent()
    }
}

triggerRestEvent函数实际上是在调用Thread.sleep 一旦睡眠过期,我们就会检查isCancelled

有没有办法在isCancelled打开时中断Thread.sleep

替代方案 - RunLoop

RunLoop 的文档建议使用 while 循环中的自定义条件围绕函数run的 while 循环。 但是我将如何设置一个计时器来切换 while 循环的执行? 显然,为了这个目的,以这种方式使用 while 循环,这些天是一种反模式吗?

Thread.sleep是不可取消的并且会阻塞一个线程。 RunLoop上旋转是低效的。 话虽如此,有几种选择:

  1. 如今,为了管理异步任务之间的依赖关系,我们将使用 Swift 并发的Task而不是Operation 在 Swift 并发中,我们有Task.sleep ,与Thread.sleep不同,它是可取消的并且不会阻塞线程。

  2. 如果您想留在OperationQueue模式中,您将使用异步自定义Operation子类(可能是此处此处显示的AsynchronousOperation ),然后您将使用计时器。 您可以将DispatchSourceTimerTimerasyncAfter与可取消的DispatchWorkItem一起使用。 你选择哪个真的不重要。 关键是确保cancel实现使Timer无效或取消DispatchWorkItemDispatchSourceTimer ,例如:

     class OneSecondOperation: AsynchronousOperation { weak var timer: Timer? override func main() { DispatchQueue.main.async { self.timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { [weak self] _ in self?.finish() } } } override func cancel() { super.cancel() timer?.invalidate() finish() } }

    请注意,您定期检查isCancelled的模式仅适用于现有循环。 例如,如果您正在进行一些迭代计算,那么这是一个非常合理的模式。 但是,如果您只是在等待,那么仅仅为了检查isCancelled而引入循环的想法是低效的。 相反,设置一个计时器并实现cancel方法,如上所示。

无论哪种方式,您都希望实现不会阻塞线程并且可以取消。 使用Operation子类,您必须自己实现。 使用 Swift 并发,您可以免费获得。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM