5

I am using dispatch group to get a data string. Here is a code and I am not sure why I get Unbalanced call to dispatch_group_leave() in this code.

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
    })
}
vcvcvcvc
  • 137
  • 4
  • 10

1 Answers1

15

Two possible issues :

Issue 1:

processStringData function might be calling its completionHandler more than once hence resulting in multiple m_group.leave() call. Number of m_group.leave() should always be equal to m_group.enter(). If you try to m_group.leave() more number of times then u entered the group u'll receive this error.

Issue 2:

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

Your code says only if completionHandler returns true leave the group so if it returns false u'll never leave the group. This will cause m_group.notify never to trigger even if once the completion block returns false and unnecessarily blocks the thread forever.

What u should do rather is

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

Issue 3:

Make sure processStringData is not changing the thread before executing the completion block. Its a common practice to switch back to main thread and execute the completion block. Entering to dispatch_group using different thread and trying to leave the group from completely different thread will also cause unbalanced call to leave.

Sandeep Bhandari
  • 19,999
  • 5
  • 45
  • 78
  • Interesting Very well explain , But I couldn't get your third point , He has already did queue. async still it is relevant ,Could you pls explain more if you know – Prashant Tukadiya Jun 27 '17 at 06:42
  • 1
    @mike-alter : Am not really sure though :) Its usually a practice to switch to main thread before executing the completion block passed as a function parameter. Like alamofire, AFNetworking in all these third party frameworks though actual network call happens on background thread before returning the server response with completion block passed as argument to their calls they do a thread switch. All they do is enclose completion() call inside DispatchQueue.main.async { completion() }. This will cause thread switch because Dispatch groups internally use semaphores switching threads like this – Sandeep Bhandari Jun 27 '17 at 06:48
  • might leave the enter and leave call unbalanced. Just a guess – Sandeep Bhandari Jun 27 '17 at 06:49
  • @mike-alter : Thank u :) – Sandeep Bhandari Jun 27 '17 at 08:39