ObjectiveC等待具有信号量的循环块

时间:2015-07-30 13:11:21

标签: ios block semaphore

我必须在method内多次使用block for loop。 我还必须等到所有blocks执行完成。

我的问题是,我无法理解我做错了什么,这导致我的整个应用程序冻结。这是代码:

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);//1 - creating semaphore
for(int i = 0; i< myObj.count; i++){
            [[DataManager shared] verifyObjectId:myObj[i].id
                                                     completionBlock:^(BOOL found) {
                                                         if(found){
                                                         //code here
                                                         dispatch_semaphore_signal(semaphore);//3 - signaling semaphore to continue
                                                         }
                                                     }];
         dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);//2 -  getting semaphore to wait
}

//I want to continue once all DB checks complete

现在,我不明白为什么semaphore不会发布,for loop将无法继续。

我真正需要的是semaphore在所有数据库检查完成后释放。理想情况下,我希望semaphorefor loop之外等待。有关如何实现这一目标的任何建议吗?

编辑:解决方案:(根据接受的答案)

// create a group
dispatch_group_t group = dispatch_group_create();
for(int i = 0; i< myObj.count; i++){
// pair a dispatch_group_enter for each dispatch_group_leave
            dispatch_group_enter(group); 
            [[DataManager shared] verifyObjectId:myObj[i].id
                                                     completionBlock:^(BOOL found) {
                                                         if(found){
                                                         //code here
                                                         }
                                                         dispatch_group_leave(group); //1 leave
                                                     }];
//Get a notification on a block that will be scheduled on the specified queue
        dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
                NSLog(@"-all done!-");
                //code here
        });
}

1 个答案:

答案 0 :(得分:3)

如果无法访问verifyObjectid:completiongBlock:,则会出现一些问题。首先,如果dispatch_semaphore_signal为真,则只调用found。如果found都是假的,那么你就会陷入僵局。这可能只是一个转录错误,你的真实代码可能不会这样做。

另一个猜测是,正在将完成块提交到您当前正在运行的队列(主队列?)如果这是真的,那肯定是一个死锁,因为你永远不会运行{{1因为它在等待dispatch_semaphore_signal。没有关于dispatch_semaphore_wait的信息,我无法分辨。

你的方法也会序列化调用,而我认为你希望它们是并行的。每次调用都必须等待前一个调用完成代码。

这里使用的更好的工具是DataManagerdispatch_apply。像这样(未经测试):

dispatch_group
在所有块都已完成运行之前,

dispatch_group_t group = dispatch_group_create(); dispatch_apply(myObj.count, dispatch_get_global_queue(0, 0), ^(size_t i){ dispatch_group_enter(group); [[DataManager shared] verifyObjectId:myObj[i].id completionBlock:^(BOOL found) { if(found){ //code here } dispatch_group_leave(group)); }]; }); dispatch_group_wait(group, DISPATCH_TIME_FOREVER); 将不会返回,这意味着dispatch_apply已经运行了“count”次。然后,您使用dispatch_group_enter等待dispatch_group_wait的所有来电。