我可以使用GCD限制并发请求吗?

时间:2013-01-18 07:07:40

标签: objective-c grand-central-dispatch

我正在异步地从数据库中获取数据。有没有什么方法可以将并发请求限制为一个数字,但仍然执行其余的?

我使用NSOperation和NSOperationQueue看到了a post 但这对我来说太复杂了。 有没有其他方法可以做到这一点? GCD可以实现吗?

3 个答案:

答案 0 :(得分:16)

这样的事情:

...
//only make one of these obviously :) remaking it each time you dispatch_async wouldn't limit anything
dispatch_semaphore_t concurrencyLimitingSemaphore = dispatch_semaphore_create(limit);
...
//do this part once per task, for example in a loop
dispatch_semaphore_wait(concurrencyLimitingSemaphore, DISPATCH_TIME_FOREVER);
dispatch_async(someConcurrentQueue, ^{
    /* work goes here */
    dispatch_semaphore_signal(concurrencyLimitingSemaphore);
}

答案 1 :(得分:0)

我建议此解决方案用于同步任务的有限并发执行:

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)
            }
        })
    }
}

这种方法开销很小:除了当前正在执行的队列之外,只有一个额外的任务被放在队列上(即一个额外的线程)。当你有大量的任务时,它会特别好。

这个gist是一个随时可用的演示,只需将代码放入游乐场。

答案 2 :(得分:-1)

简单的方法是设置n个串行队列

struct dataCalls {
    let n:Int
    func fetchIt(){
        print ("Done",n)
    }

    init(n:Int){
        self.n=n
    }
}

var dataCallsArray: [dataCalls]=[]
var qArray:[dispatch_queue_t] = []
let n = 5
for i in 1...50 {
    dataCallsArray.append(dataCalls(n:i))
}

for _ in 1...n {
    qArray.append(dispatch_queue_create(nil, nil))
}

var i = 0
for data in dataCallsArray {
    dispatch_async(qArray[i%n], {() -> Void in data.fetchIt()})
    i++
}