gpt4 book ai didi

ios - DispatchQueue.asyncAfter 没有像我想象的那样工作?

转载 作者:可可西里 更新时间:2023-11-01 01:23:35 25 4
gpt4 key购买 nike

我正在开发一个应用程序,其中我尝试调试的 403 禁止错误实际上是由您每分钟可以向端点发出的请求数量的上限引起的(愚蠢的我)。

很好,我决定将我的网络请求放到 DispatchQueue 上(无论如何更好的并发设计)并使用 asyncAfter(deadline:execute:) 函数在每个请求之间造成 4 秒的延迟。

我的程序设计是列表中的每个项目都调用一个函数,在该函数中,一些工作(请求)被放入该调度队列。见下文:

class ViewController

let serialQueue = DispatchQueue(label: "networkRequests")

func myFirstFunc {
for item in items {
self.mySecondFunc(item: item, completionHandler: {(completionItem) in
// you shouldn't need this
})
}
}

func mySecondFunc(item: someType, completionHandler: @escaping (String?) -> Void) {

let task = session.dataTask(with: request, completionHandler: {(data, response, error) in
// stuff
completionHandler(changedItem)
})
self.serialQueue.asyncAfter(deadline: .now() + 4.0) {
task.resume()
print(Date())
}
}
}
}

我认为这可行的方式是,无论该函数是否被不同的线程同时调用,包含在 asyncAfter(deadline:execute:) 调用中的代码将排队,并且下一个闭包不会开始执行直到最后一个关闭完成并且又过了 4 秒。

这没有用——print(Date()) 在打印时间之间没有延迟。

我在 unix 中使用 sleep() 函数修复了它,但我很好奇这在使用 GCD 的 Swift 中如何工作。

谢谢!

编辑:专门寻找具有功能的正确方法,其中单个线程执行每个请求,这样线程就会被阻塞,直到前一个线程完成,中间有 4 秒的延迟。

最佳答案

此处列出的其他答案是有效的,但它们并不像应有的那样可靠。以固定时间间隔调用 task.resume() 并不能保证在这些时间间隔实际发送请求。您受制于 URLSession.shared 维护的内部队列。以 4 秒为间隔添加任务并不意味着它们一定会在该时间内发送。它还不能保证请求需要多长时间(想想服务质量差的移动网络)。至于 Data(contentsOf:),它完全没有提供真正的功能或定制,例如错误处理。

一个更稳健的解决方案是使用 DispatchGroup 并仅在前一个请求完成后 4 秒发起一个新请求。

class ViewController

let serialQueue = DispatchQueue(label: "networkRequests")
let networkGroup = DispatchGroup()

func myFirstFunc {
for item in items {
self.mySecondFunc(item: item, completionHandler: {(completionItem) in
// you shouldn't need this
})
}
}

func mySecondFunc(item: someType, completionHandler: @escaping (String?) -> Void) {

let task = session.dataTask(with: request, completionHandler: {(data, response, error) in
// stuff
completionHandler(changedItem)

Thread.sleep(forTimeInterval: 4) // Wait for 4 seconds
networkGroup.leave() // Then leave this block so the next one can run
})
self.networkGroup.notify(queue: serialQueue) {
networkGroup.wait() // Wait for the previous block to finish
networkGroup.enter() // Enter a new block
task.resume()
print(Date())
}
}
}

这将保证每个后续请求在前一个请求完成后的 4 秒内发送,并且不依赖外部因素(如 URLSession 的内部队列或网络稳定性)来维持适当的时机,而不牺牲 URLSession 的现代功能。

关于ios - DispatchQueue.asyncAfter 没有像我想象的那样工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42472095/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com