[英]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
上旋转是低效的。 话虽如此,有几种选择:
如今,为了管理异步任务之间的依赖关系,我们将使用 Swift 并发的Task
而不是Operation
。 在 Swift 并发中,我们有Task.sleep
,与Thread.sleep
不同,它是可取消的并且不会阻塞线程。
如果您想留在OperationQueue
模式中,您将使用异步自定义Operation
子类(可能是此处或此处显示的AsynchronousOperation
),然后您将使用计时器。 您可以将DispatchSourceTimer
或Timer
或asyncAfter
与可取消的DispatchWorkItem
一起使用。 你选择哪个真的不重要。 关键是确保cancel
实现使Timer
无效或取消DispatchWorkItem
或DispatchSourceTimer
,例如:
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.