从DispatchGroup wait获取最新结果

时间:2018-06-23 11:45:35

标签: ios swift grand-central-dispatch

问题描述:

我想通过'DispatchGroup'执行一堆异步任务,当所有任务完成时,它返回结果。此外,我想设置限制流程的超时,并在该时间之前将成功结果发送给我。我使用了以下结构:

代码块

let myGroup = DispatchGroup()

var result = [Data]()
for i in 0 ..< 5 {
    myGroup.enter()

    Alamofire.request("https://httpbin.org/get", parameters: ["foo": "bar"]).responseJSON { response in
        print("Finished request \(i)")
        result.append(response.data)
        myGroup.leave()
    }
}

// Timeout for 10 seconds
myGroup.wait(timeout: DispatchTime(uptimeNanoseconds: 10000000000))

myGroup.notify(queue: .main) {
    return result
}

如果发生超时,如何获得最新结果?

1 个答案:

答案 0 :(得分:0)

好的,因此您可以正确使用DispatchGroup的输入/离开功能,但是在访问这些结果时遇到了麻烦。我认为尝试同时使用waitnotify会出错,这两个函数提供了两个通常不一起使用的不同功能。设置完工作项后,您有两个选择:

  1. wait方法

此函数阻止调用队列,并同步等待传入的挂墙时间过去,或组中的所有工作项离开。因为它阻止了调用者,所以在此函数中始终保持超时很重要。

  1. notify方法

该函数接收目标队列,并在组中的所有工作项都已完成时运行一个块。在这里,您基本上是在所有工作项都完成后要求系统异步通知您。由于这是异步,我们通常不必担心超时,它不会阻塞任何内容。

  1. 异步wait(这似乎是您想要的?)

如果您似乎希望在所有工作项都完成后得到通知,但又有超时的情况,那么我们必须自己做,这并不是那么棘手。我们可以为DispatchGroup类添加一个简单的扩展名...

extension DispatchGroup {

    func notifyWait(target: DispatchQueue, timeout: DispatchTime, handler: @escaping (() -> Void)) {
        DispatchQueue.global(qos: .default).async {
            _ = self.wait(timeout: timeout)
            target.async {
                handler()
            }
        }
    }

}

这个简单的函数在全局后台队列上异步调度,然后调用wait,它将等待所有工作项完成或指定的超时,以先到者为准。然后它将在指定的队列中回调您的处理程序。


这就是理论,您怎么使用它。我们可以使您的初始设置完全相同

let myGroup = DispatchGroup()

var result = [Data]()
for i in 0 ..< 5 {
    myGroup.enter()

    Alamofire.request("https://httpbin.org/get", parameters: ["foo": "bar"]).responseJSON { response in
        print("Finished request \(i)")
        result.append(response.data)
        myGroup.leave()
    }
}

然后使用我们的新功能等待结束

myGroup.notifyWait(target: .main,
                   timeout: DispatchTime.now() + 10) {
    // here you can access the `results` list, with any data that has
    // been appended by the work items above before the timeout
    // was reached
}