【问题标题】:Wait for multiple AFNetworking requests to complete等待多个 AFNetworking 请求完成
【发布时间】:2016-06-16 17:53:44
【问题描述】:

我需要等待几个 AFNetworking 请求完成,我尝试使用调度组,但似乎无法正确处理。

这是我的代码:

dispatch_group_t group = dispatch_group_create();

for (int k = 0; k < 10 ; k++) {
    dispatch_group_enter(group);

    [[AFHTTPSessionManager manager] GET:@"http://google.com/" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"success");
        dispatch_group_leave(group);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"failure");
        dispatch_group_leave(group);
    }];
}

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

NSLog(@"DONE");

问题是它卡在 dispatch_group_wait 上,因为既没有调用成功块,也没有调用失败块。

我该如何解决?

【问题讨论】:

  • 您是否尝试过使用 dispatch_group_notify?
  • 是的,这行得通。但是,这并不能解决我的问题。由于应用程序的构建方式(我继承了项目),我需要停止执行该方法。
  • 那很不幸;您可能需要考虑重构它。如果你阻塞线程,你将浪费一个线程,它唯一的工作就是等待另一个线程做某事。 libdispatch 将启动用于服务队列的线程限制为 64 个,因此根据您的应用程序正在执行的操作,它可能会成为问题。

标签: objective-c afnetworking grand-central-dispatch


【解决方案1】:

completionBlock 的调度队列。如果NULL(默认),则使用主队列。

dispatch_group_t group = dispatch_group_create();

dispatch_queue_t queue = dispatch_queue_create("com.app", DISPATCH_QUEUE_CONCURRENT);

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.completionQueue = queue;
for(int k = 0; k < 10; k++) {
    dispatch_group_enter(group);

    dispatch_async(queue, ^{
        NSLog(@"%d", k);
        [manager GET:@"http://baidu.com/" parameters:nil progress:nil success:^(NSURLSessionDataTask *_Nonnull task, id _Nullable responseObject) {
             NSLog(@"success");
             dispatch_group_leave(group);
         } failure:^(NSURLSessionDataTask *_Nullable task, NSError *_Nonnull error) {
             NSLog(@"failure");
             dispatch_group_leave(group);
         }];
    });
}

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

NSLog(@"DONE");

【讨论】:

    【解决方案2】:

    试试这个,

      dispatch_group_t group = dispatch_group_create();
    
    for (int k = 0; k < 10 ; k++) {
        dispatch_group_enter(group);
    
        [[AFHTTPSessionManager manager] GET:@"http://google.com/" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            NSLog(@"success");
            dispatch_group_leave(group);
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            NSLog(@"failure");
            dispatch_group_leave(group);
        }];
    }
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    
        NSLog(@"All done");
    
    });
    

    dispatch_group_notify 将在所有任务完成后被调用。

    【讨论】:

      【解决方案3】:

      你可以使用PromiseKit。非常强大。

      顺序

            [self.manager GET:@"http://www.error-url.ss/" parameters:nil].then(^(id responseObject, AFHTTPRequestOperation *operation){
              NSLog(@"first request completed for operation: %@", operation.request.description);
              return [self.manager GET:@"http://www.apple.com" parameters:nil];
          }).then(^{
              NSLog(@"second request completed");
          }).catch(^(NSError *error){
              NSLog(@"error happened: %@", error.localizedDescription);
              NSLog(@"original operation: %@", error.userInfo[AFHTTPRequestOperationErrorKey]);
          });
      

      或(根据您的要求)

              [PMKPromise when:@[
                             [self.operationManager GET:@"ip" parameters:nil].then(^(){numberOfOperationsCompleted ++;}),
                             [self.operationManager GET:@"get" parameters:nil].then(^(){numberOfOperationsCompleted ++;})
                             ]].then(^(){
              //do something when all operations are finished
          });
      

      【讨论】:

        【解决方案4】:

        你可以使用这个辅助函数来阻塞主线程。

        static inline void hxRunInMainLoop(void(^block)(BOOL *done)) {
        __block BOOL done = NO;
        block(&done);
        while (!done) {
            [[NSRunLoop mainRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow:.1]];
        }
        }
        

        你还需要实现一个计数器并在成功或失败时递增它。

        - (void)test {
          __block int count = 0;
        
          hxRunInMainLoop(^(BOOL *done) {
        
            for (int i = 0; i < 10; i++) {
        
            [AFHTTPSessionManager manager] GET:@"http://google.com/" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
              NSLog(@"success");
              count++;
              if (count == 9) {
                *done = YES;
              }
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
              NSLog(@"failure");
              count++;
              if (count == 9) {
                *done = YES;
              }
            }];
        }
        

        这将阻塞主线程,直到 done 设置为 YES。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-05-19
          • 2016-10-04
          • 1970-01-01
          • 1970-01-01
          • 2016-12-12
          • 1970-01-01
          • 2011-07-01
          • 1970-01-01
          相关资源
          最近更新 更多