Unable to break loop with semaphore

181 views Asked by At

I am trying to add a list of async tasks in DispatchWorkItem using semaphore.

 func performStickerWorkItems(_ stickers: [String]) {
    let queue = DispatchQueue.global(qos: .background)
    workItem = DispatchWorkItem { [weak self] in
        for sticker in stickers {
            guard let item = self?.workItem, !item.isCancelled else {
                print("cancelled")
                break
            }
            let semaphore = DispatchSemaphore(value: 0)
            self?.addSticker(sticker: sticker) {
                print("S: \(sticker)")
                semaphore.signal()
            }
            semaphore.wait()
        }
        
        self?.workItem = nil
    }
    
    queue.async(execute: workItem!)
    workItem?.notify(queue: .main) {
        self.updateButton(false)
    }
}

And in between if I go back, I want it to break the loop and process. For that, I use the cancel method to cancel DispatchWorkItem but it doesn't break the loop.

@IBAction func backWasPressed(_ sender: Any) {
    workItem?.cancel()
    navigationController?.popViewController(animated: true)
}

Any solution to break the loop and process of semaphore when I pressed the back button?

2

There are 2 answers

2
Jayesh Patel On

Cancel it from main thread

DispatchQueue.main.async {
   workItem?.cancel()
   workItem = nil
}
0
Kozmotronik On

In the DispatchWorkItem documentation says that:

Cancellation does not affect the execution of a work item that has already begun.

Since your work item has already begun to execution, you need to find out another workaround to cancel that work. You can alternatively use a separate Thread since it conforms your need because it does have an effective cancellation support.