如何处理3个不同的同时异步调用

时间:2014-12-12 13:53:02

标签: ios objective-c multithreading objective-c-blocks mutability

以下是我的担忧:出于某种原因,我必须检索并分组来自3个不同网络请求结果的答案。一旦其中3个返回,我必须调用completionBlock并将所有结果传递给它。 使用NSOperation API,我设法做了类似的事情:

Session * session = [[ServiceLocator sharedInstance] serviceForName:ServiceLocatorNameUserRepository];


NSString * urlMethod = @"POST";
NSDictionary * params = @{kParkadomWebServiceUser : session.currentUser.userID};

NSMutableDictionary * records = [NSMutableDictionary new];

NSOperation * currentBooking = [self performRequestWithPath:API_BOOKING_INPROGRESS
                                                         method:urlMethod
                                                      parameter:params
                                                     completion:^(id json, NSError * error)
                                                     {
                                                         records[@"current"] = error ? error : json;

                                                     }];

NSOperation * upcomingBookings = [self performRequestWithPath:API_BOOKING_UPCOMING
                                                         method:urlMethod
                                                      parameter:params
                                                     completion:^(id json, NSError * error)
                                                     {
                                                         records[@"upcoming"] = error ? error : json;

                                                     }];

NSOperation * pastBookings = [self performRequestWithPath:API_BOOKING_HISTORY
                                                   method:urlMethod
                                                parameter:params
                                               completion:^(id json, NSError * error)
                                               {
                                                   records[@"past"] = error ? error : json;

                                               }];


NSBlockOperation * completionOperation = [NSBlockOperation blockOperationWithBlock:^{
    completion([records copy], nil);
}];
[completionOperation addDependency:currentBooking];
[completionOperation addDependency:upcomingBookings];
[completionOperation addDependency:pastBookings];

[[NSOperationQueue mainQueue] addOperation:completionOperation];

其中,完成显然是作为入口参数给出的完成块。 performRequestWithPath:方法:参数:完成:创建一个NSOperation,将其添加到全局队列并返回它,所以我在这里进行了3次Web调用。然后我创建一个块操作并将依赖项添加到前一个3块,以便在3个块完成之前不会触发它。

我关心的是NSMutableArray的东西。做这样的事情似乎是一个糟糕的设计,我不确定它是否真的可以在案例2调用完全同时完成时进行错误验证。 (注意我在perform ...中确定了在主队列中调用完成块的方法。)

有任何反馈意见吗?建议,批评,理论......我全都开放了:)

2 个答案:

答案 0 :(得分:2)

如果您的“记录”字典用于在这些异步调用中添加键/值的单一目的,您可以通过在添加三个的代码周围放置@synchronized(records){...}来轻松完成此操作值。

如果完成块在主队列上执行,则它们不能同时执行。但是,您必须仔细检查您的代码:三个操作可能在完成块完成之前完成!

答案 1 :(得分:1)

您需要添加同步。

@synchronized(myArray) {
  [myArray doSomething];
}

例如,在您的代码中:

@synchronized(records) {
    records[@"past"] = error ? error : json;
}

编辑:@ gnasher729提出了一个好处,即如果它们在主线程上运行完成块,那么就不需要同步。