iOS GCD 与异步块同步
iOS GCD Sync with Async Block
我有一个带块的异步函数:
[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 只是在等待块的结束。
我怎样才能让它等待其块中的异步函数结束?
您可以将 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
如果您想在完成一系列异步任务后启动某个进程,但又想让这些任务 运行 彼此并发(尤其是对于网络请求,可以提供比 运行 按顺序连接它们更好的性能):
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
});
就个人而言,我什至可能倾向于使用异步 NSOperation
子类模式来对 performAsyncTaskCompletion
执行更彻底的重构。然后你可以将它们添加到指定 maxConcurrentOperationCount
的 NSOperationQueue
中,从而实现相同的并发,同时还控制并发程度。但希望以上说明了这个想法:运行 并发任务,但检测这些任务的完成而不会阻塞主线程。
我有一个带块的异步函数:
[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 只是在等待块的结束。 我怎样才能让它等待其块中的异步函数结束?
您可以将 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
如果您想在完成一系列异步任务后启动某个进程,但又想让这些任务 运行 彼此并发(尤其是对于网络请求,可以提供比 运行 按顺序连接它们更好的性能):
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
});
就个人而言,我什至可能倾向于使用异步 NSOperation
子类模式来对 performAsyncTaskCompletion
执行更彻底的重构。然后你可以将它们添加到指定 maxConcurrentOperationCount
的 NSOperationQueue
中,从而实现相同的并发,同时还控制并发程度。但希望以上说明了这个想法:运行 并发任务,但检测这些任务的完成而不会阻塞主线程。