【问题标题】:Correct way to perform async operations sequentially按顺序执行异步操作的正确方法
【发布时间】:2019-02-24 14:25:27
【问题描述】:

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

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 调用没有回调 - 我认为这告诉我主队列被阻塞,但我不明白为什么。

【问题讨论】:

标签: swift grand-central-dispatch dispatch-queue


【解决方案1】:

您应该使用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()
    }
}

【讨论】:

  • 他需要一个连续剧,这就是排队的原因
  • @Sh_Khan 如果您在其上执行异步任务,则声明串行队列将无法确保串行执行。这就是DispatchGroup 的用途。
  • 我将整个东西包装在一个串行队列中,试图阻止它阻塞主队列
  • 这行得通。我在之前的项目中尝试过几次,应该标记为接受的答案。
  • 好吧,让我失望。使用group.notify 而不是group.wait,我发现不需要 需要串行队列。谢谢!
【解决方案2】:

也许这只是一个错字但基本上不要运行队列synchronously。

然后在循环的外部(!)使用notify而不是wait,并在队列中打印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】:

我不认为您的主队列已锁定,否则您的应用程序可能会无限加载,就好像它崩溃了(在 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。但我不是异步调用方面的专家。

希望对你有帮助

【讨论】:

    猜你喜欢
    • 2021-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多