Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unbalanced call to dispatch_group_leave() in duplicated for loop

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
    })
}
like image 989
vcvcvcvc Avatar asked Jun 27 '17 03:06

vcvcvcvc


1 Answers

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.

like image 95
Sandeep Bhandari Avatar answered Nov 05 '22 13:11

Sandeep Bhandari