调度组等待永远卡住

时间:2019-05-29 21:01:11

标签: ios swift grand-central-dispatch

我有一个使用Alamofire发出多个HTTP请求的功能。我想等待它们全部完成以返回值。但是,它卡在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)
    }

2 个答案:

答案 0 :(得分:1)

使用异步处理程序完成所有异步任务后,就可以正确设置所有设置。唯一的问题是您使用的DispatchGroup模式不正确。这是正确的模式(这是伪代码):

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
}

答案 1 :(得分:1)

假设正在主队列上调用getActionField,并且了解到Alamofire在主队列上调用了它的完成块(我认为设计很差),那么自从调用{{ 1}}现在正在阻止主队列,并且无法对wait进行任何调用。

绝对不能使用同一线程来调用leavewait

最简单的解决方案是将leave的使用替换为wait

notify

通常应避免使用group.notify(queue: DispatchQueue.main) { completion(resreturn) } 。尤其是如果您已经在使用完成处理程序并且不需要等待该方法。