我有一个带有块的异步函数:
[self performAsyncTaskCompletion:(void(^) () )
{
//Do Something
}
];
我需要多次调用此函数,但需要以同步方式调用。我试图使用GCD队列:
dispatch_queue_t queue = dispatch_queue_create("com.MyApp.task", NULL);
for (int i = 0; i < array.count; i++)
{
dispatch_sync(queue, ^{
[self performAsyncTaskCompletion:(void(^) () )
{
//Do Something
}
];
});
}
但它不起作用,因为dispatch_sync只等待块的结束。 如何让它等待其块中的异步函数结束?
答案 0 :(得分:7)
如果要在完成一系列异步任务后启动某个进程,可以使用调度组,但是希望允许这些任务相互并行运行(特别是对于网络请求,可以提供这些任务)比顺序运行它们要好得多的性能:
dispatch_group_t group = dispatch_group_create();
for (int i = 0; i < array.count; i++) {
dispatch_group_enter(group);
[self performAsyncTaskCompletion: ^{
//Do Something
dispatch_group_leave(group);
}];
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// do this when its all done
});
就我个人而言,我甚至倾向于使用异步performAsyncTaskCompletion
子类模式对NSOperation
进行更激进的重构。然后,您可以将这些添加到NSOperationQueue
并指定maxConcurrentOperationCount
,从而实现相同的并发性,同时还控制并发度。但希望上面说明了这个想法:同时运行任务,但是在没有阻塞主线程的情况下检测这些任务的完成。
答案 1 :(得分:1)
您可以将dispatch_async
与semaphores:
示例:
- (void)performAsyncTaskCompletion:(void (^)())block {
if (block) {
block();
}
}
- (void)runChainOfOperations {
static dispatch_once_t onceToken;
static dispatch_semaphore_t semaphore;
static dispatch_queue_t queue;
dispatch_once(&onceToken, ^{
semaphore = dispatch_semaphore_create(1);
queue = dispatch_queue_create("com.example.MyApp", NULL);
});
NSArray *array = @[@1, @2, @3, @4, @5];
static long counter = 0;
for (int i = 0; i < array.count; i++) {
dispatch_async(queue, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
[self performAsyncTaskCompletion:^{
sleep(10);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"%ld", counter++);
});
dispatch_semaphore_signal(semaphore);
}];
});
}
}
控制台输出:
2015-04-12 21:28:06.047 HKTest[9497:1136830] 0
2015-04-12 21:28:16.023 HKTest[9497:1136830] 1
2015-04-12 21:28:26.025 HKTest[9497:1136830] 2
2015-04-12 21:28:36.029 HKTest[9497:1136830] 3
2015-04-12 21:28:46.031 HKTest[9497:1136830] 4