Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async NSURLConnection, Concurrent NSOperation, when to use NSRunLoop?

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

like image 526
cin Avatar asked Jan 19 '23 21:01

cin


1 Answers

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.

like image 171
cin Avatar answered Apr 07 '23 13:04

cin