为什么在 DispatchQueue.main.asyncAfter(... 中,具有不同延迟的操作同时执行
Why are in DispatchQueue.main.asyncAfter(..., operations with different delay executing at same time
我的代码:
let operationStart = Date()
for i in 0...20 {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5 * Double(i)) {
let distance = operationStart.distance(to: Date())
print("operation \(i) executed after \(distance)")
}
}
输出:
操作 0 在 0.001116037368774414 之后执行
操作 1 在 0.5226989984512329 之后执行
操作 2 在 1.0015490055084229 之后执行
...
操作 9 在 4.940060019493103 之后执行
操作 10 在 5.499879002571106 之后执行
操作 11 在 6.049391031265259 之后执行
操作 12 在 6.0494760274887085 之后执行
操作 13 在 7.105716943740845 之后执行
操作 14 在 7.105777978897095 之后执行
8.189378023147583之后执行的操作15
操作16在8.189532995223999之后执行
操作 17 在 9.30673599243164 之后执行
操作 18 在 9.306856036186218 之后执行
操作 19 在 10.423419952392578 之后执行
操作 20 在 10.423549056053162 之后执行
如何避免这种情况?我需要以相同的延迟执行操作。
为此目的使用 DispatchSourceTimer
,因为如果您将来有一堆 asyncAfter 调用)。当它合并时,整体速度应该保持基本一致,但它会将它们合并在一起,让你的计时器更卡顿
let operationStart = Date()
let queue = DispatchQueue(label: "com.domain.app.timer")
var timer = DispatchSource.makeTimerSource(queue: queue)
var i = 0
//for i in 0...20 {
timer.schedule(deadline: .now(), repeating: 0.5, leeway: .seconds(0))
timer.setEventHandler { // `[weak self]` only needed if you reference `self` in this closure and you want to prevent strong reference cycle
let distance = operationStart.distance(to: Date())
i = i+1
if i == 20 {
timer.cancel()
}
print("operation \(i) executed after \(distance)")
}
timer.resume()
使用 asyncAfter
时应考虑的事项 here 是:
Work is guaranteed to execute after the deadline, but not necessarily at that exact moment. In other words, it may take longer than the deadline, but it will never happen before the deadline.
所以使用 Timer
会更适合你的情况,正如@jawadAli 回答的那样。
我的代码:
let operationStart = Date()
for i in 0...20 {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5 * Double(i)) {
let distance = operationStart.distance(to: Date())
print("operation \(i) executed after \(distance)")
}
}
输出:
操作 0 在 0.001116037368774414 之后执行 操作 1 在 0.5226989984512329 之后执行 操作 2 在 1.0015490055084229 之后执行 ... 操作 9 在 4.940060019493103 之后执行 操作 10 在 5.499879002571106 之后执行 操作 11 在 6.049391031265259 之后执行 操作 12 在 6.0494760274887085 之后执行 操作 13 在 7.105716943740845 之后执行 操作 14 在 7.105777978897095 之后执行 8.189378023147583之后执行的操作15 操作16在8.189532995223999之后执行 操作 17 在 9.30673599243164 之后执行 操作 18 在 9.306856036186218 之后执行 操作 19 在 10.423419952392578 之后执行 操作 20 在 10.423549056053162 之后执行
如何避免这种情况?我需要以相同的延迟执行操作。
为此目的使用 DispatchSourceTimer
,因为如果您将来有一堆 asyncAfter 调用)。当它合并时,整体速度应该保持基本一致,但它会将它们合并在一起,让你的计时器更卡顿
let operationStart = Date()
let queue = DispatchQueue(label: "com.domain.app.timer")
var timer = DispatchSource.makeTimerSource(queue: queue)
var i = 0
//for i in 0...20 {
timer.schedule(deadline: .now(), repeating: 0.5, leeway: .seconds(0))
timer.setEventHandler { // `[weak self]` only needed if you reference `self` in this closure and you want to prevent strong reference cycle
let distance = operationStart.distance(to: Date())
i = i+1
if i == 20 {
timer.cancel()
}
print("operation \(i) executed after \(distance)")
}
timer.resume()
使用 asyncAfter
时应考虑的事项 here 是:
Work is guaranteed to execute after the deadline, but not necessarily at that exact moment. In other words, it may take longer than the deadline, but it will never happen before the deadline.
所以使用 Timer
会更适合你的情况,正如@jawadAli 回答的那样。