【问题标题】:Dispatch Group wait stuck forever调度组等待永远卡住
【发布时间】:2019-05-29 21:01:10
【问题描述】:

我有一个使用 Alamofire 发出多个 HTTP 请求的函数。我想等待所有这些都完成以返回一个值。但是,它卡在 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)
    }

【问题讨论】:

    标签: ios swift grand-central-dispatch


    【解决方案1】:

    假设 getActionField 在主队列上被调用,并且理解 Alamofire 在主队列上调用其完成块(我认为糟糕的设计),你遇到了一个死锁,因为对 wait 的调用是现在阻塞了主队列,无法调用leave

    您绝不能使用同一个线程来调用waitleave

    最简单的解决方案是将wait 的使用替换为notify

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

    一般情况下,您应该避免使用wait。特别是如果您已经在使用完成处理程序并且不需要等待该方法。

    【讨论】:

      【解决方案2】:

      您已经正确设置了这一切,在所有异步任务完成后使用完成处理程序。唯一的问题是您错误地使用了 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
      }
      
      

      【讨论】:

      • 这也是我正在使用的。仅供参考 - group.enter() 调用在另一个之后立即调用,因为闭包立即返回。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      • 1970-01-01
      • 2013-11-24
      • 2012-02-24
      • 1970-01-01
      • 1970-01-01
      • 2019-08-13
      相关资源
      最近更新 更多