首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >等待异步方法在for循环中完成。

等待异步方法在for循环中完成。
EN

Stack Overflow用户
提问于 2014-10-13 15:17:09
回答 4查看 4.5K关注 0票数 6

我有一个包含三个异步方法的for循环,我想在这三个异步方法完成之后进行一些处理。

代码语言:javascript
运行
复制
 -(void)getAllUsersInformations{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
           for(User *user in users){
              [self getUserInfo:user];
           }
      //Here, I want to reload the table view for example, after finishing the for loop (executing the whole three methods).
    });
}

-(void)getUserInfo:(User*)user{
     [self getInformations:user];
     [self getExperiences:user];
     [self getEducation:user];
}

你有什么技术可以得到这个结果吗?非常感谢。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-10-13 15:48:51

GCD的一种方法是使用dispatch_group。因此,在启动异步任务之前,调用dispatch_group_enter,然后在异步任务完成时调用dispatch_group_leave,然后创建一个dispatch_group_notify,该dispatch_group_notify将在异步任务完成时被调用。您可以将它与完成块模式结合起来(这对于异步方法来说是个好主意):

  1. 如果getInformationsgetExperiencesgetEducation本身都是异步方法,那么首先需要某种机制来了解它们何时完成。一个常见的解决方案是为每个模块实现一个完成块模式。例如: //添加了completionHandler参数,该参数将在检索//完成“信息”时调用。-(Void)getInformations:(user*) completionHandler:(void (^)(void))completionHandler {/做您以前做的任何事情,但是在异步任务的完成块中,调用这个// completionHandler() /,例如NSURLRequest *请求;NSURLConnection sendAsynchronousRequest:请求队列:nil完成处理程序:^(NSURLResponse *response,NSData *data,NSError *connectionError) { //处理这里的请求//重要的是,如果(completionHandler) { completionHandler();}},完成处理程序应该//被称为_inside_这个块;}; 对getExperiencesgetEducation也重复此过程。
  2. 然后,可以使用调度组通知完成这三个请求的每个请求何时完成,并在发生此操作时调用getUserInfo中的一个完成块: //添加的完成处理程序,只有在getInformations、/ getExperiencesgetEducation都完成时才会调用。/这利用了我们添加到上述三种//方法中的完成块- (void)getUserInfo:(User*)user completionHandler:(void (^)(void))completionHandler { dispatch_group_t group = dispatch_group_create();//启动三个请求dispatch_group_enter(组);自获取体验:用户完成处理程序:^{ dispatch_group_leave(组);};dispatch_group_enter(组);自getEducation:用户完成处理程序:^{dispatch_group_leave(组);};//此块只有在完成dispatch_group_notify(组、dispatch_get_main_queue()、^{ if (completionHandler) {completionHandler())时才能异步调用;});}
  3. 然后在getAllUsersInformations中重复这个过程: //调用新getUserInfo,使用调度组跟踪是否完成了//所有请求-(getAllUsersInformations{ dispatch_group_t组= dispatch_group_create();for(用户*用户){dispatch_group_enter(组);self getUserInfo:用户完成处理程序:^{dispatch_group_leave(组);};}dispatch_group_notify(组,dispatch_get_main_queue(),^{ self.tableView reloadData;});}

最后两个想法:

  1. 在概述了所有这些之后,我必须承认,我可能会将这些请求封装在并发/异步自定义NSOperation子类中,而不是使用分派组。请参阅Concurrency Programming Guide的“为并发执行配置操作”一节。这是对代码的更激进的重构,所以我不会在这里讨论这个问题,但是它允许您限制将同时运行的这些请求的数量,从而减少潜在的超时问题。
  2. 我不知道这些用户请求中有多少正在进行,但是您可能需要考虑在用户信息输入时更新UI,而不是等待所有的内容完成。同样,这也是对代码进行更激进的重构,但可能会导致更有响应性的东西。
票数 15
EN

Stack Overflow用户

发布于 2014-10-13 15:42:03

尝试完成一个块,如果方法是异步的,就不能用for循环来完成。在完成前面的操作之后,您必须一个一个地调用getUserInfo。我想这会解决你的问题。

代码语言:javascript
运行
复制
  -(void)getAllUsersInformations{
    [self registerUserAtIndex:0];
  }

  - (void) registerUserAtIndex: (NSInteger ) userIndex
  {
  RegisterOperation *op = [[RegisterOperation alloc] initWithUser:[users objectAtIndex:userIndex]];
  [RegisterOperation setResultCompletionBlock:^(BOOL *finished, NSInteger userIndex) {
      dispatch_async(dispatch_get_main_queue(), ^{
      if (userIndex++ < [users count] {
         [self registerUserAtIndex:userIndex++];
      } else {
         [myTableView reloadData];
      }
   }];
  [[NSOperationQueue mainQueue] addOperation:op];
 }

希望这能帮到你。

票数 0
EN

Stack Overflow用户

发布于 2017-01-05 11:25:23

用快速回答Rop

代码语言:javascript
运行
复制
func processData()
{
    let group: dispatch_group_t  = dispatch_group_create()

    for item in data as! Object {
        dispatch_group_enter(group)
        item.process(completion: {() -> (Void) in
          dispatch_group_leave(group)
        })
      }

    dispatch_group_notify(group, dispatch_get_main_queue(), {
        //Do whatever you want
      })
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26343351

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档