4

I'm trying to run NSURLConnection async in a secondary thread (target is iOS4), for this I have created a concurrent NSOperation, I think I'm almost there, but am not clear on the following:

1) in iOS4 NSOperationQueue addOperation starts the operation in a new thread, because of the use of GCD, based on Technical Q&A QA1712, however, my tests (simulator and iPad) show that start() is always called on the main thread, any idea, do I need a check here: if on main thread then spawn a new one?

2) if start was actually called on a secondary thread by addOperation(), then I could start my async NSURLConnection by scheduling on the current NSRunLoop:

[self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[self.connection start];

like the LinkedImageFetcher example here and I would not need to loop until completed with:

do {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (!isCompelted);

3) assuming my custom NSOperation start() is called on the main thread and 2) is correct, and I spawn a new thread in start() to call my custom main() method with:

[NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];

In my main() I then do need to run the current thread run loop:

do {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (!isCompelted);

This is the only instance I've managed to run NSURLConnection in a concurrent NSOperation, but I'm not sure I do need to run the RunLoop, if the thread was supplied by the GCD as the tech notes state, could I follow the logic in 2) or would I still have to run the thread's runloop? How can I test a thread supplied by GCD?

Many thanks for any elucidation

cin
  • 131
  • 1
  • 6
  • use simple connection method(as @vaubry suggested- Asynchronous NSURLCOnnection) and then use NSOperationQueue for parsing. This will help you in achieving what you want. – Ravin May 13 '11 at 13:33

2 Answers2

9

Well, I eventually worked this out so thought people might be interested in the details:

1) start() was called on the main thread because I was using [NSOperationQueue mainQueue] rather than creating a new queue with [[NSOperationQueue allc] init]. However a check in NSOperation start() for whether the current thread was the mainThread or not and then calling main() directly from there or by spawning a new thread (in case we were on the mainThread) did not hurt.

2) I realized that LinkedImageFetcher is far too complex for an understanding of run loops and threads, and unnecessarily so, because the topic is not that complicated. All that is needed within the start() method is to keep the secondary thread run loop going until we're done (isCompleted), all the run loop does for a NSURLConnection is listening to the inputs from the connection and firing callbacks (didreceivereponse, didreceivedata, etc.).

3) yes running the run loop is necessary to get connection callbacks on that same (secondary in this case) thread.

For more see Run Loops in Threading Programming Guide.

cin
  • 131
  • 1
  • 6
  • 1
    Just thought I'd leave a comment and say thanks a ton! I wanted to implement multiple downloads using NSOperation and NSOperationQueue, simply because I can cancel and limit the number of simultaneous downloads instead of implementing my own queue manager. Your question and your answer, in collaboration with Dave Dribin's blog (http://www.dribin.org/dave/blog/archives/2009/05/05/concurrent_operations/) helped me wrap my head around the concept of using background threads with asynchronous calls. I still have some doubts, but I'll ask them after going through the docs again!:) Thanks again! – codeBearer Nov 03 '11 at 23:12
0

I'm not sure to understand what you're trying to achieve : NSURLConnection API has a built-in async method initWithRequest:delegate:

Is there any specific reason why you can't use this ?

vdaubry
  • 11,369
  • 7
  • 54
  • 76
  • 6
    Simpler design and scalability, I'd like parsing the response in the bg too, and I need to run more than one request at the same time. Thanks – cin Apr 30 '11 at 13:09
  • Using NSOperationQueue allows you to add NSOperation instances which download data. On the queue you can set a max of operations to run at a time. You may find 2 or 4 to be optimal for performance. With GCD you would have to manage the max yourself, plus NSOperation is easy to cancel. – Brennan Jul 16 '12 at 19:30