ios - Objective C 等待带有信号量的循环 block

标签 ios block semaphore

我必须使用 block 运行一个 method,在一个 for 循环 中多次运行。 我还必须等到所有 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

现在,我不明白,为什么信号量不释放,for循环不继续。

我真正需要的是在所有数据库检查完成后释放信号量。理想情况下,我希望信号量for 循环 之外等待。关于如何实现这一点有什么建议吗?

编辑:解决方案:(基于接受的答案)

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

最佳答案

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

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

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

这里使用的更好的工具是 dispatch_applydispatch_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 直到所有 block 都完成运行后才会返回,这意味着 dispatch_group_enter 已运行“count”次。然后使用 dispatch_group_wait 等待对 dispatch_group_leave 的所有调用。

关于ios - Objective C 等待带有信号量的循环 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31724781/

相关文章:

swift - 如何在 Swift 中创建通用闭包

objective-c - 通过 `id` 在 Objective-C 中调用 Swift 闭包

ios - 找不到您输入的 apple id 或您的密码不正确

ruby - 枚举器 `Array#each` 's {block} can' t 总是更改数组值?

ios - AVKit 无法流式传输 Dropbox Link 视频

python - 如何防止对USB设备等资源的并发访问?

swift - 等待 Swift 包中的 URLSession 完成

javascript - Javascript/jQuery ajax调用同步的常用做法

ios - 在 iOS 中导入文件 : UIDocumentPicker vs UIDocumentBrowser

ios - 使用 sprite 工具包的级别菜单的持久性