你说:
假设您有一个数组,并且您想要遍历数组中的每个元素并调用一个函数......该函数接受该元素作为参数。
了解一系列异步任务何时完成的基本 GCD 模式是调度组:
let group = DispatchGroup()
for item in array {
group.enter()
someAsynchronousMethod { result in
// do something with `result`
group.leave()
}
}
group.notify(queue: .main) {
// what to do when everything is done
}
// note, don't use the results here, because the above all runs asynchronously;
// return your results in the above `notify` block (e.g. perhaps an escaping closure).
如果您想将其限制为最大并发数为 4,则可以使用非零信号量模式(但请确保不要从主线程执行此操作),例如
let group = DispatchGroup()
let semaphore = DispatchSemaphore(value: 4)
DispatchQueue.global().async {
for item in array {
group.enter()
semaphore.wait()
someAsynchronousMethod { result in
// do something with `result`
semaphore.signal()
group.leave()
}
}
group.notify(queue: .main) {
// what to do when everything is done
}
}
实现上述目标的等效方法是使用自定义异步Operation 子类(使用定义here 或here 的基类AsynchronousOperation),例如
class BarOperation: AsynchronousOperation {
private var item: Bar
private var completion: ((Baz) -> Void)?
init(item: Bar, completion: @escaping (Baz) -> Void) {
self.item = item
self.completion = completion
}
override func main() {
asynchronousProcess(bar) { baz in
self.completion?(baz)
self.completion = nil
self.finish()
}
}
func asynchronousProcess(_ bar: Bar, completion: @escaping (Baz) -> Void) { ... }
}
然后您可以执行以下操作:
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 4
let completionOperation = BlockOperation {
// do something with all the results you gathered
}
for item in array {
let operation = BarOperation(item: item) { baz in
// do something with result
}
operation.addDependency(completionOperation)
queue.addOperation(operation)
}
OperationQueue.main.addOperation(completion)
通过非零信号量方法和这种操作队列方法,您可以将并发度设置为您想要的任何值(例如 1 = 串行)。
但也有其他模式。例如。 Combine 也提供了实现这一目标的方法https://stackoverflow.com/a/66628970/1271826。或者借助 iOS 15、macOS 12 中引入的新的 async/await,您可以利用新的协作线程池来约束并发程度。
有很多不同的模式。