How to resume NSOperationQueue timeout in iOS?

I have already successfully implemented NSOperationQueue in the application.

I have one operation queue that can have 1000 NSOperations, as shown below.

@interface Operations : NSOperation @end @implementation Operations - (void)main { NSURL *url = [NSURL URLWithString:@"Your URL Here"]; NSString *contentType = @"application/json"; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request addValue:contentType forHTTPHeaderField: @"Content-Type"]; NSError *err = nil; NSData *body = [NSJSONSerialization dataWithJSONObject:postVars options:NSJSONWritingPrettyPrinted error:&err]; [request setHTTPBody:body]; [request addValue:[NSString stringWithFormat:@"%lu", (unsigned long)body.length] forHTTPHeaderField: @"Content-Length"]; [request setTimeoutInterval:60]; NSHTTPURLResponse *response = nil; NSError *error = nil; NSData *resData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; } @end 

Now for this queue, I add all 1000 operations at a time. I am adding an operation as shown below.

 Operations *operation = [[Operations alloc]init]; [downloadQueue addOperation:operation]; 

Now what happens, the time interval is 60 as [request setTimeoutInterval:60]

So, think that after 60 seconds, if 300 operations out of 1000 operations have ended, another 700 operations will cause a request timeout error.

So what should I do in this case.

Is it possible to resume unsuccessful operations? Or should I perform the operation again and add it to the queue.

Is there a better mechanism than this?

+6
source share
3 answers

My initial mood would be yes, just create new operations for the programmed queries and send them back to the queue. This is simply simpler since you already have the logic to add these operations to your queries. BUT:

  • Be careful not to end up in an endless loop. If only one of them fails for any reason, your turn will continue to interrupt work. I would keep a crash account so that you know to stop retrying the request after some finite number of attempts.

  • If you KNOW that a large number will always fail, consider revising them in some way. One option would be a chain of dependencies. eg. You could try adding 200 of your options, waiting for NSOperation, the next 200, another waiting for NSOperation, another waiting op, etc. Make the first wait op dependent on these first 200 requests. Then make the next 200 depend on the first wait op, etc .:

    • [package 1: first 200 requests]
    • [wait 1: op, which is waiting for the whole batch 1]
    • [batch 2: next 200, everyone is waiting 1)
    • [wait 2: op, which is waiting for the whole batch 2]
    • [series 3: the next 200, everyone is waiting 2]
    • and etc.
  • Basically, like 2, but instead of "wait" op, do "done" op. Suppose you have an array of 1000 send requests: Toss 200 to the queue, then the “done” op, which depends on these 200. When the “done” op is executed (by definition, AFTER 200), it can then pull the next 200 from array and toss them (plus a new "made" op).

(maybe even think about pausing the wait “pause” for a few seconds to give the server a break)

In other words, C # 2 and # 3, I say "bang 200 right away, wait, and then blow the next 200, wait, etc.". (200 arbitrary for my part, you know better than me about what is the best number for your situation)

+3
source

You can implement the NSURLConnectionDelegate connection:didFailWithError: method to check if the synchronous request has failed, and if the error was that the request has expired. Then try connecting again in the delegate callback.

I should note that Apple strongly recommends using NSURLSession over NSURLConnection , as many methods from NSURLConnection now deprecated.

+2
source

The first point - do not let them work at the same time! You can easily flood a mobile data connection if you try to run even 10 requests at the same time. So, before anything else, set maxConcurrentOperationCount in the queue to about 5.

Only this, most likely, will significantly reduce your problem, and you may not need to do anything.

You should also take a look at using NSURLSession , and so you can also look at deleting the operation queue and using HTTPMaximumConnectionsPerHost to control the number of requests at a time.

If you still get a crash, then one of the "recursive type" options, as the other answers discuss, is a workable solution. I would add a count of attempts to a subclass of the operation to make tracking easier, and if it doesn’t work, then check how many times it failed, and decide whether to create a new copy of the operation and add it to the queue or raise an alert.

+2
source

All Articles