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_asyncsemaphores 一起使用:

示例:

- (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 执行更彻底的重构。然后你可以将它们添加到指定 maxConcurrentOperationCountNSOperationQueue 中,从而实现相同的并发,同时还控制并发程度。但希望以上说明了这个想法:运行 并发任务,但检测这些任务的完成而不会阻塞主线程。