Правильный способ последовательного выполнения асинхронных операций - PullRequest
0 голосов
/ 20 сентября 2018

Мне нужно выполнить асинхронную операцию для каждого элемента в массиве, по одному за раз.Эта операция перезванивает в главной очереди.

func fetchResults(for: array, completion: () -> Void) {

    var results: [OtherObject]: []
    let queue = DispatchQueue(label: "Serial Queue")
    queue.sync {

        let group = DispatchGroup()
        for object in array {

            group.enter()
            WebService().fetch(for: object) { result in
                // Calls back on main queue
                // Handle result
                results.append(something)

                group.leave()
            }
            group.wait()
        }
    }

    print(results) // Never reached
    completion()
}

Вызов WebService не перезванивает - я думаю, он говорит, что основная очередь заблокирована, но я не могу понять, почему.

Ответы [ 3 ]

0 голосов
/ 20 сентября 2018

Может быть, это просто опечатка, но в основном не запускайте очередь sync хронически.

Тогда вместо wait используйте notify вне (!) Цикла и выведите resultsв очереди.

queue.async {

    let group = DispatchGroup()
    for object in array {

        group.enter()
        WebService().fetch(for: object) { result in
            // Calls back on main queue

            // Handle result
            results.append(something)

            group.leave()
        }
    }
    group.notify(queue: DispatchQueue.main) {
        print(results)
        completion()
    }
}
0 голосов
/ 20 сентября 2018

Я не думаю, что ваша основная очередь заблокирована, иначе вы, вероятно, имели бы бесконечную загрузку в вашем приложении, как если бы оно падало (в MacOS это точно).

Вот что сработало для меня, может быть, это поможет:

class func synchronize(completion: @escaping (_ error: Bool) -> Void) {

    DispatchQueue.global(qos: .background).async {

        // Background Thread
        var error = false
        let group = DispatchGroup()
        synchronizeObject1(group: group){ error = true }
        synchronizeObject2(group: group){ error = true }
        synchronizeObject3(group: group){ error = true }
        group.wait() // will wait for everyone to sync

        DispatchQueue.main.async {
            // Run UI Updates or call completion block
            completion(error)
        }
    }
}




class func synchronizeObject1(group: DispatchGroup, errorHandler: @escaping () -> Void){

    group.enter()
    WebservicesController.shared.getAllObjects1() { _ in

        // Do My stuff

        // Note: if an error occures I call errorHandler()

        group.leave()
    }
}

Если бы я сказал, это может прийти от queue.sync вместо queue.async.Но я не эксперт по асинхронным вызовам.

Надеюсь, это поможет

0 голосов
/ 20 сентября 2018

Вы должны использовать group.notify() вместо group.wait(), так как последняя является синхронной блокирующей операцией.

Я также не вижу точки отправки в очередь, если вы отправляете только однурабочий элемент один раз.

func fetchResults(for: array, completion: () -> Void) {

    var results: [OtherObject]: []
    let group = DispatchGroup()
    for object in array {
        group.enter()
        WebService().fetch(for: object) { result in
            // Calls back on main queue
            // Handle result
            results.append(something)

            group.leave()
        }
    }

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