Search code examples
iosswiftiphonegrand-central-dispatch

DispatchSemaphore cause app frozen, how to resolve it


when i run code, i click iphone home button, then reopen my app,my app is frozen.i feel uncertain,why?

let queue = DispatchQueue(label: "com.aiswei.asw.monitior.search",qos: .default, attributes: .concurrent)
        let semaphore = DispatchSemaphore(value: 30)
        let minX = 2
        let maxX = 254
        self.index = minX
self.index = minX
        let count = maxX - minX + 1
        let lock = NSLock()
        for i in minX...maxX {
            queue.async {
                semaphore.wait()
                lock.lock()
                // request some server api  result
                 NetCenter.requestAPi { (result) in
                    semaphore.signal()
                }
            
                lock.unlock()
              
            }
        
        }


Solution

  • I would expect this to try to create over 250 threads, which you don't want to do. That said, my suspicion is that the actual problem is with coming in the foreground is elsewhere; possibly in NetCenter. You're probably deadlocking the main queue (especially if NetCenter is written in the same style).

    Rather than kicking off a ton of DispatchWorkItems and then blocking them, you can achieve the same thing by using a single DispatchWorkItem on a serial queue, with your semaphore. The serial queue will get rid of the need for the lock. This serializes 30 operations at a time, which is what I think you want.

        let queue = DispatchQueue(label: "com.aiswei.asw.monitior.search")
        let semaphore = DispatchSemaphore(value: 30)
    
        queue.async {
            let minX = 2
            let maxX = 254
            for _ in minX...maxX {
                semaphore.wait()
                NetCenter.requestAPi { (result) in
                    semaphore.signal()
                }
            }
        }
    }
    

    I'm assuming here that requestAPi is an async method and will schedule its completion handler on some queue other than queue. (If NetCenter uses the same queue as this function, than that would definitely deadlock.)