如何打断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 文档建议在函数 run
周围使用 while 循环,并在 while 循环中使用自定义条件。但是我如何设置一个计时器来切换 while 循环执行呢?显然,为了这个目的,以这种方式使用 while 循环,现在是一种反模式吗?
Thread.sleep
是 non-cancelable 并阻塞线程。在 RunLoop
上旋转是低效的。话虽如此,还有一些选择:
现在,为了管理异步任务之间的依赖关系,我们会达到 Swift 并发的 Task
而不是 Operation
。在 Swift 并发中,我们有 Task.sleep
,与 Thread.sleep
不同,它是可取消的,不会阻塞线程。
如果您想保持 OperationQueue
模式,您可以使用异步自定义 Operation
子类(可能是 [=33= 中显示的 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 并发,您可以免费获得它。
我已经在 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 文档建议在函数 run
周围使用 while 循环,并在 while 循环中使用自定义条件。但是我如何设置一个计时器来切换 while 循环执行呢?显然,为了这个目的,以这种方式使用 while 循环,现在是一种反模式吗?
Thread.sleep
是 non-cancelable 并阻塞线程。在 RunLoop
上旋转是低效的。话虽如此,还有一些选择:
现在,为了管理异步任务之间的依赖关系,我们会达到 Swift 并发的
Task
而不是Operation
。在 Swift 并发中,我们有Task.sleep
,与Thread.sleep
不同,它是可取消的,不会阻塞线程。如果您想保持
OperationQueue
模式,您可以使用异步自定义Operation
子类(可能是 [=33= 中显示的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 并发,您可以免费获得它。