I propose this solution for the limited simultaneous execution of synchronous tasks:
func dispatch_async_batch(tasks: [() -> ()], limit: Int, completion: (() -> ())?) { if tasks.count > 0 || completion != nil { let q = dispatch_queue_create("dispatch_async_batch", DISPATCH_QUEUE_CONCURRENT); let sema = dispatch_semaphore_create(limit); dispatch_async(q, { for task in tasks { dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER) dispatch_async(q, { task() dispatch_semaphore_signal(sema) }) } if let completion = completion { dispatch_barrier_async(q, completion) } }) } }
This approach has a small overhead: only one additional task is placed in the queue (i.e., one additional thread) in the direction currently being performed. This is especially good when you have a large total amount of tasks.
This gist is a ready-to-use demo, just put the code in the playground.
source share