swift - 如何快速同步循环
问题描述
我正在尝试编写一个用于对列表进行排序的算法,并且我使用对 google maps api 的网络调用(API 请求)来获取有关列表中两点之间距离的信息。
我正在使用 while 循环,并遍历列表,直到列表的大小为 0。
在每次迭代中,我都会进行一次网络调用,在它响应后,我会从列表中删除一些内容。
我尝试在下面的代码中使用信号量,但它没有按预期工作。
let semaphore = DispatchSemaphore(value: 1)
let dispatchQueue = DispatchQueue(label: "taskQueue")
dispatchQueue.async {
while unvistedPoints.count > 0{
print("The size of the list is ", unvisited.count)
self.findNextVistablePoint(visited: visitedPoints, unvisted: unvistedPoints, completion: { (pointToVisit) in
let indexofPointToVisit = unvistedPoints.firstIndex(where: {$0 === pointToVisit})
unvistedPoints.remove(at: indexofPointToVisit!)
visitedPoints.append(pointToVisit)
semaphore.signal()
})
semaphore.wait()
}
打印语句应打印 6,5,4,3,2,1。
解决方案
这是一些简化的游乐场代码,演示了使用信号量来确保您的请求被串行执行:
import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
class SomeAsyncClass {
var unvistedPoints = [ 6,5,4,3,2,1 ]
let dispatchQueue = DispatchQueue(label: "taskQueue") // serial queue
let semaphore = DispatchSemaphore(value: 1)
public func doAsyncStuff() {
for point in self.unvistedPoints {
print("Queuing point \(point)")
dispatchQueue.async {
// block before sending the network request
self.semaphore.wait()
self.makeFakeNetworkRequest(point, completion: {
// request complete
print("Completed \(point)")
self.semaphore.signal()
})
}
}
}
func makeFakeNetworkRequest(_ point:Int, completion:()->()) {
let interval = TimeInterval(exactly: (arc4random() % 3) + 1)!
print("Point \(point): Sleeping for: \(interval)")
Thread.sleep(forTimeInterval: interval)
print("Point \(point): Awoken after: \(interval)")
completion()
}
}
var c = SomeAsyncClass()
c.doAsyncStuff()
这是输出:
Queuing point 6
Queuing point 5
Queuing point 4
Point 6: Sleeping for: 3.0
Queuing point 3
Queuing point 2
Queuing point 1
Point 6: Awoken after: 3.0
Completed 6
Point 5: Sleeping for: 3.0
Point 5: Awoken after: 3.0
Completed 5
Point 4: Sleeping for: 3.0
Point 4: Awoken after: 3.0
Completed 4
Point 3: Sleeping for: 3.0
Point 3: Awoken after: 3.0
Completed 3
Point 2: Sleeping for: 3.0
Point 2: Awoken after: 3.0
Completed 2
Point 1: Sleeping for: 3.0
Point 1: Awoken after: 3.0
Completed 1
话虽如此,这不是最好的方法。您最好使用为此目的而设计的 iOS 构造,即 OperationQueue——它具有精细的并发控制 ( maxConcurrentOperationCount
),并且可以用作 URLSession ( delegateQueue
) 的基础。如果它适合您的需要,我建议使用该构造。
推荐阅读
- sql - Postgres Where 查询不适用于字符变化数据类型的数值
- vb.net - 无法在某些项目的组合框中设置默认项
- powershell - 底层连接已关闭:发送时出现意外错误
- css - 如何在材质 ui 上使用过渡使模态居中并使其响应?
- excel - 将一列的参考编号复制到另一列
- php - 如何将adwords代码放入php的ajax查询方法中?
- arrays - node.js 在间隔中迭代数组特定时间
- arrays - 根据多个数组值过滤文件行
- javascript - 即使它不在 console.log (...) 中,值为 null
- java - JdbcTemplate 插入 XmlType 在较大尺寸上失败