我有一組異步執行的請求。但是,每個下一個請求只應在前一個請求完成時纔開始(由於數據依賴性)。如何執行一個接一個的多個異步請求
由於所有請求都應該按照正確的順序完成,因此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