Hello for a project I'm working on I have to perform n-SLRequest in background, So what I tought is to add these requests to an NSOperationQueue as the code below show
- (void)performBatchRequest:(void(^)(void))completion
{
NSURL *url = [NSURL URLWithString:@"https://api.twitter.com/1.1/direct_messages/new.json"];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
ACAccount *account = [self getStoredAccount];
for (NSDictionary *user in self.inviteList)
{
[queue addOperationWithBlock:^
{
NSDictionary *params = @{@"screen_name" :user[@"name"],@"text":@"message" }
SLRequest *inviteRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter
requestMethod:SLRequestMethodPOST
URL:url
parameters:];
[inviteRequest setAccount:account];
[inviteRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
if (error)
{
NSLog(@"Errror");
}
}];
}];
}
self.inviteList = nil;
if (completion)
{
completion();
}
}
Now What I'm wondering is if this is the best approach I can use to perform multiple SLRequest in background. Any suggestion / correction is really appreciated
Your completion handler wont't work as you expect: since the requests are all started asynchronously, you immediately reach the
if (completion) { completion(); }
statement - but nothing is completed yet.There are a number of approaches to handle such asynchronous patterns. The objective is to signal completion of a number of asynchronous tasks. One easy way is to setup a counter which is initially equal the number of tasks. Whenever one task finishes (or fails) increment the counter by one (carefully synchronized, e.g. executing on a dedicated queue or the main thread). When the counter reaches zero, invoke your completion handler.
Otherwise, the approach is viable.
However, you might want to explicitly control the maximum number of concurrent requests executed by the underlaying network layer. If latency is a problem, you should increase the number of concurrent requests.
NSOperationQueue
has a propertymaxConcurrentOperations
which is per default equal to the number of CPUs.The max concurrent requests will likely be two (for CPU bound queues and two cores). In your scenario, this happens to be OK, anyway. However, the optimal number of concurrent requests depend on many factors, which may be out of your control: the server, or the quality of the connection for example.
If you have very large data to transmit, I would set to 1 - since the limiting factor is bandwidth - not latency.
Otherwise, up to 4 or 5. The more concurrent requests, the more memory is used in your app!
Note:
NSULRConnection
may force an upper limit of max concurrent requests, depending on host or IP or other factors, too.Conclusion:
Given an average environment with average connection quality, a user won't notice much of an improvement if you try to optimize with a high number of concurrent requests. But setting up a high number will increase the risk of your app to choke due to memory issues.
Leave it at two, and be happy. ;)