Search code examples
swiftmacosgrand-central-dispatch

Is there a way to cancel a DispatchQueue concurrentPerform operation?


Is there a way to stop a concurrentPerform operation?

let count = arr.count
let group = DispatchGroup()
group.enter()
DispatchQueue.concurrentPerform(iterations: count, execute: { i in
    if stop { group.leave(); return }  // Crashes with EXC_BAD_INSTRUCTION
    // ..
})
group.wait()

This crashes with EXC_BAD_INSTRUCTION after a few iteration. Seems like the group.leave() is not exiting the operation. How to exit cancel the operation? Basically, what I am trying to do is loop an array concurrently and break out of it if some condition is met, without using Objective-C bridge to use concurrent enumeration.


Solution

  • DispatchQueue.concurrentPerform causes the block to be executed the specified number of times, and waits for all iterations to complete. There is no way to prevent that. (The blocks run in parallel if the target queue is a concurrent queue.)

    Of course each work item can “early return” if some condition is met, but that won't affect the other work items.

    Your code crashes because leave() is called on the dispatch group more times than enter().