对for循环中的dispatch_group_leave()进行不平衡调用

时间:2017-06-27 03:58:31

标签: ios concurrency dispatch

我正在使用调度组来获取数据字符串。这是一个代码,我不知道为什么我在这段代码中得到Unbalanced call to dispatch_group_leave()

var queue = DispatchQueue(label: "extractStringQueue", attributes: .concurrent)
queue.async {
  let m_group = DispatchGroup() 
    let weeks = self.weekDataArray 

    for week in weeks {
        for day in week.dayDataArray {
             m_group.enter()
             day.processStringData(dataName, completionHandler: { (data, response, error) in 
                    if true {
                        // Process 
                        m_group.leave()    
                    }
              })
        }
    }

    m_group.notify(queue: queue, execute: {
     // CompletionHandler
    })
}

1 个答案:

答案 0 :(得分:4)

两个可能的问题:

问题1:

processStringData函数可能多次调用其completionHandler因此导致多次m_group.leave()调用。 m_group.leave()的数量应始终等于m_group.enter()。如果您尝试m_group.leave()次更多次,那么您将进入该组,您将收到此错误。

问题2:

    m_group.enter()
    day.processStringData(dataName, completionHandler: { (data, response, error) in 
    if true {
       // Process 
       m_group.leave()    
    }
})

您的代码仅在completionHandler返回true时才会显示该组,因此如果它返回false,您将永远不会离开该组。即使完成块返回false并且不必要地永久阻塞线程,这也会导致m_group.notify永远不会触发。

你应该做的是

    m_group.enter()
    day.processStringData(dataName, completionHandler: { (data, response, error) in 
    if true {
       // Process    
    }
    m_group.leave() 
})

问题3:

确保processStringData在执行完成块之前不更改线程。通常的做法是切换回主线程并执行完成块。使用不同的线程输入dispatch_group并尝试从完全不同的线程离开该组也会导致不平衡的呼叫离开。