代码之家  ›  专栏  ›  技术社区  ›  Ashley Mills

按顺序执行异步操作的正确方法

  •  0
  • Ashley Mills  · 技术社区  · 6 年前

    我需要对数组中的每个元素执行异步操作,一次一个。此操作回调主队列。

    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 回复  |  直到 6 年前
        1
  •  4
  •   Dávid Pásztor    6 年前

    你应该使用 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()
        }
    }
    
        2
  •  2
  •   vadian    6 年前

    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()
        }
    }
    
        3
  •  0
  •   Crocobag    6 年前

    我不认为你的主队列被锁定了,否则你的应用程序可能会有无限的负载,就像它崩溃了一样(在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

    希望有帮助

    推荐文章