我有一组异步执行的请求。但是,每个下一个请求只应在前一个请求完成时才开始(由于数据依赖性)。如何执行一个接一个的多个异步请求
由于所有请求都应该按照正确的顺序完成,因此DispatchGroup()
似乎没用。
我目前实施DispatchSemaphore()
,但我觉得这不是最好的解决方案,因为我想确保所有请求都在后台执行。
let semaphore = DispatchSemaphore(value: requests.count)
for request in requests {
apiManager().performAsyncRequest(request, failure: { error in
print(error); semaphore.signal()
}) { print(“request finished successful”)
// Next request should be performed now
semaphore.signal()
}
}
semaphore.wait()
有没有更好的方法来执行此操作?
注意:基于执行下面的答案之一我遇到apiManager()
不是线程安全的(由于使用Realm数据库)。
为了保持这个问题,明确并与performAsyncRequest
一个线程安全的定义,认为在一个线程安全的方式回答:
public func performAsyncRequest(_ requestNumber: Int, success: @escaping (Int) -> Void)->Void {
DispatchQueue(label: "performRequest").async {
usleep(useconds_t(1000-requestNumber*200))
print("Request #\(requestNumber) starts")
success(requestNumber)
}
}
解决方案与DispatchSemaphore
let semaphore = DispatchSemaphore(value: 1)
DispatchQueue(label: "requests").async {
for requestNumber in 0..<4 {
semaphore.wait()
performAsyncRequest(requestNumber) { requestNumber in
print("Request #\(requestNumber) finished")
semaphore.signal()
}
}
}
随着预期的输出:
Request #0 starts
Request #0 finished
Request #1 starts
Request #1 finished
Request #2 starts
Request #2 finished
Request #3 starts
Request #3 finished
不成功的尝试Operation
var operations = [Operation]()
for requestNumber in 0..<4 {
let operation = BlockOperation(block: {
performAsyncRequest(requestNumber) { requestNumber in
DispatchQueue.main.sync {
print("Request #\(requestNumber) finished")
}
}
})
if operations.count > 0 {
operation.addDependency(operations.last!)
}
operations.append(operation)
}
let operationQueue = OperationQueue.main
operationQueue.addOperations(operations, waitUntilFinished: false)
用不正确的输出:
Request #0 starts
Request #1 starts
Request #2 starts
Request #3 starts
Request #0 finished
Request #3 finished
Request #2 finished
Request #1 finished
我的感觉是,它也应该能够得到这个与Operation
的工作,但我不知道它是否会比使用DispatchSemaphore
更好。
您定位的是哪个Swift版本? – xpereta
Swift 3.我刚刚用DispatchSemaphore的实现编辑了这个问题,但我想知道在这种情况下是否应该使用它。 – Taco
你是指“所有请求都在后台执行”是什么意思?如果apiManager()不是线程安全的,则不可能执行任何调用来在后台线程上执行AsyncRequest。 – xpereta