I have a function making multiple HTTP requests with Alamofire. I want to wait for all of them to finish in order to return a value. However, it gets stuck at dispatch.wait()
class func getActionField(fieldid: String, completion: @escaping (_ res: [String: [Double]]) -> Void) {
var resreturn: [String: [Double]] = ["temperature":[], "humidity":[], "ph":[], "light":[]]
let dispatch = DispatchGroup()
dispatch.enter()
Alamofire.request(url + "aktionsdaten/temperatur/" + fieldid, method: .get).responseJSON{ response in
resreturn["temperature"] = response.result.value as! NSArray as? [Double] ?? [0.0,0.0]
dispatch.leave()
}
dispatch.enter()
Alamofire.request(url + "aktionsdaten/light/" + fieldid, method: .get).responseJSON{ response in
resreturn["light"] = response.result.value as! NSArray as? [Double] ?? [0.0,0.0]
dispatch.leave()
}
dispatch.enter()
Alamofire.request(url + "aktionsdaten/ph/" + fieldid, method: .get).responseJSON{ response in
resreturn["ph"] = response.result.value as! NSArray as? [Double] ?? [0.0,0.0]
dispatch.leave()
}
dispatch.enter()
Alamofire.request(url + "aktionsdaten/feuchtigkeit/" + fieldid, method: .get).responseJSON{ response in
resreturn["humidity"] = response.result.value as! NSArray as? [Double] ?? [0.0,0.0]
dispatch.leave()
}
dispatch.wait()
completion(resreturn)
}
Assuming that getActionField
is being called on the main queue and the understanding that Alamofire calls its completion blocks on the main queue (bad design in my opinion), you are running into a deadlock since the call to wait
is now blocking the main queue and none of the calls to leave
can be made.
You must never use the same thread to call wait
and leave
.
The simplest solution is to replace the use of wait
with notify
.
group.notify(queue: DispatchQueue.main) {
completion(resreturn)
}
You should avoid the use of wait
in general. Especially if you are already using a completion handler and there is no need for the method to wait.
You have this all set up correctly, using a completion handler after all your asynchronous tasks are finished. The only problem is that you're using the DispatchGroup pattern incorrectly. Here's the correct pattern (this is pseudocode):
let group = DispatchGroup()
group.enter()
queue1.async {
// ... do task here ...
group.leave()
}
group.enter()
queue2.async {
// ... do task here ...
group.leave()
}
group.enter()
queue3.async {
// ... do task here ...
group.leave()
}
// ... more as needed ...
group.notify(queue: DispatchQueue.main) {
// finished! call completion handler or whatever
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With