Диспетчерская группа ждать застряли навсегда - PullRequest
1 голос
/ 30 мая 2019

У меня есть функция, делающая несколько HTTP-запросов с Alamofire.Я хочу дождаться, пока все они закончат, чтобы вернуть значение.Тем не менее, он застревает в 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 ]

1 голос
/ 30 мая 2019

Предполагая, что getActionField вызывается в главной очереди, и понимая, что Alamofire вызывает свои блоки завершения в главной очереди (плохой дизайн, на мой взгляд), вы попадаете в тупик, так как вызов waitтеперь блокировка основной очереди и ни один из вызовов leave невозможен.

Вы никогда не должны использовать один и тот же поток для вызова wait и leave.

Самое простое решениезаменяет использование wait на notify.

group.notify(queue: DispatchQueue.main) {
    completion(resreturn)
}

Вам следует избегать использования wait в целом.Особенно, если вы уже используете обработчик завершения, и метод не нуждается в ожидании.

1 голос
/ 30 мая 2019

У вас все настроено правильно, с использованием обработчика завершения после завершения всех ваших асинхронных задач.Единственная проблема заключается в том, что вы используете шаблон 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
}

...