concurrent NSOperation, why start on main thread? - ios

I am studying this source code which demonstrates how to use NSURLConnection with NSOperation:
link
I am confused about the code at line 76
if (![NSThread isMainThread])
{
[self performSelectorOnMainThread:#selector(start)
withObject:nil waitUntilDone:NO];
return;
}
Why is the author making sure that the code is run on main thread?
Isn't the whole point of NSOperation to not run on main thread and in a background thread so that it doesn't block?
The code is from this article that explains it although it doesn't answer my questions: http://eng.pulse.me/concurrent-downloads-using-nsoperationqueues/

From the NSURLConnection docs, you can see;
NSURLConnection’s delegate methods—defined by the NSURLConnectionDelegate Protocol protocol—allow an object to receive informational callbacks about the asynchronous load of a URL request. [...] These delegate methods are called on the thread that started the asynchronous load operation for the associated NSURLConnection object.
Starting an operation on an NSURLConnection works on any thread, however it's very useful to get the delegate callbacks on the GUI/main thread if you want to - for example - display progress.

If you use NSURLConnection asynchronous you need to launch this operation on Main Thread for getting the callback. If you launch an asynchronous NSURLConnection from a background thread you can lose it callback if your background thread from you launched your NSURLConnection is busy for other activity.

If you call start method in main thread, A current operation main method will be run in main thread, but you push current operation to NSOperationQueue(not main queue), start method call in sub thread, a current operation main method in sub thread.
Sub Thread Photo
Main Method in Sub Thread

If this is an example I believe that this is put into there in order for you to see the difference between having that code in there and not. If this code were to be executing concurrently and is supposed to leave your main thread alive then indeed that section of code should not be there however it may have been put in there for you to remove and see the difference. However you are indeed correct. Browsing through the rest of the file it looks like that should not be in there if you are wanting to leave your main thread open.

The reason is, on iOS 4.0+, wether the operation is concurrent or not, the operation is ran in a background thread. Since in this case the operation is concurrent, the method exists immediately and the thread is killed so no delegate method is called (NSURLConnection calls delegate method on the thread from which it started).
The only options are, either to start an NSRunLoop (very hectic) or use a thread that already has one (main thread) - so that's why the start method is run from the main thread.
Has nothing to do with updating UI as many suggested (although i understand the point but the entire reason to run an NSURLConnection in a queue is to process the delegate callbacks in a seperate thread to avoid blocking UI). That wasn't the intention of the author, the fact that it is UIKit safe is a mere consequence.

Related

Returning to a thread with GCD from a delegate

We're implementing a sync system where some operations are sent to a SAP Mobile Platform server asynchronously, and when the operations are completed, we receive a delegate call from a proprietary SDK.
This delegate method is run on a random thread, not using GCD.
We would like to do send the operations - then wait until the delegate method is called which means the operations are complete - then resume the work when this is finished (or a time-out has occured). I know this may seem synchronous, but we cannot allow the user to modify data while the operations are not finished yet to ensure data integrity.
The Sync ViewController is doing some heavy syncing work and is using GCD, and updates a progress bar and some text in the UI thread.
Now, when the delegate method is called, we want to call another method on the Sync ViewController, but this call is apparently done in the wrong thread.
My question is how to execute these methods in the same thread that GCD was executing them before the delegate was called.
Things we tried:
Just calling the methods. Then these methods are called in the wrong thread, namely the thread where the delegate method is in.
Posting a notification on a chosen thread, we don't know the exact thread where the Sync ViewController was working in.
Any ideas?
If you are already using GCD, then you must know the dispatch queue this work is being done on, so isn't it simply a case of scheduling a block, either synchronously or asynchronously, on that queue?
- (void)someDelegateMethod:(id)someValue {
dispatch_async(self.myDispatchQueue, ^{
[self doInterestingThingWith:someValue];
});
}

Do RestKit completion blocks run on the main UI thread?

My code tells me it is via [NSThread currentThread] isMainThread] and the fact that I can show a UIAlertView as well. This seems unexpected because my understanding is that requests are dispatched asynchronously.
I'd throw in some relevant code, but it's nothing special. I POST an object via the RKObjectManager and the success and failure completion blocks execute on the main UI thread (even though I am definitely doing stuff in the background after the request completes).
I'm confused.
What's going on?
RKObjectManager behind the scenes creates and posts an RKObjectRequestOperation (which is essentially representation of your POST request) into NSOperationQueue to perform all the networking and mapping stuff asynchronously in the background thread.
When request is finished and response processed - default behavior is to run success or failure callbacks on the main thread. This is nice quick setup that helps you to build an app very fast and easy (and not worry about updating UI on the right thread).
You can easily change that behavior, RKObjectRequestOperation has 2 properties, successCallbackQueue and failureCallbackQueue, you can set them to be another background thread, and then when you need to change something on the UI side, just wrap that change into a block and post to main queue:
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
}];
The reason why you want requests are dispatched asynchronously because you don't want UI Thread (which is main thread) blocked by the request. because when it blocked , your App wont react user's action , that's a bad user experience.
Then after the request is done, you want to let the user know it, so the dispatched thread must return to main thread. in your situation, that's the completion block. then you can do things like show alert on the main thread.
I hope this is the answer you want.

how to prevent main thread ios from killing background thread

I have a method in my AppDelegate that saves a NSManagedObjectContext passed as a parameter. This method may be called on either the main thread or a background thread, and I want to ensure that when this method is called the main thread doesn't kill it halfway through when the user terminates the program or what have you. How do I prevent the main thread from killing this thread when this method is being executed?
I also want to do this for writing data to a plist file -- this also may happen outside of the main thread.
I am doing all my background work by way of GCD and dispatch_async
Brad Larson had some suggestions on this post that should help you.
In your appDelegate, when your app is getting pushed to the background, it calls applicationDidEnterBackground. From this routine, you can see if your method is currently in progress, and can behave accordingly.
Depending on how long your task takes to run there are two options:
If it will take significantly less than 5 seconds, you can just have your applicationDidEnterBackground wait until your task is completed before releasing. If you take longer than 5 seconds, your app will just get force-killed.
If it could be a while, you can try beginBackgroundTaskWithExpirationHandler: to start a background task that finishes off your task.

NSOperation using GCD, ensure all on the same thread

I have a 'concurrent' NSOperation, and during it's work it uses some controller classes that internally use GCD. When these controller classes return with their completion block, the completion block is on another thread.
I know I could store the current thread in the operation start method and run performSelectorOnThread:, but ideally I would like to wrap the completion in a GCD block and dispatch onto the same thread as the operation started on. Is this even possible with GCD, as I can only specify a queue to dispatch to.
What's the best way to bring this work back onto the same thread that the operation started on? Apart from what I already suggested... unless this is the best way.
When the operation is completed the UI update or any other related things has to be done on main thread. The following link might be useful to you about CGD.
http://www.raywenderlich.com/4295/multithreading-and-grand-central-dispatch-on-ios-for-beginners-tutorial
I don't think this is really possible/advisable. Since iOS 4 onwards, NSOperation is using GCD , and as GCD is managing my threads - I don't think I should be keeping references to them.
I did find some util methods for executing blocks of code on a particular thread. See Practical Blocks by Mike Ash or this article doing similar thing.
As my goal was to keep my core data calls on the same thread, instead I opted to upgrade my code to use parent/child managed object contexts with NSPrivateQueueConcurrencyType, and then used performBlock: on the managed object context to ensure all my call backs on the separate threads got executed correctly by core data.

NSURLConnection and sendAsynchronousRequest:queue:completionHandler: - does the completion block run in the main thread

If I use NSURLConnection with sendAsynchronousRequest:queue:completionHandler:, do I need to take any particular precautions inside the completion handler? Specifically, is sending asynchronously directly via NSURLConnection the same/similar as using dispatch_async in that the completion block would need to come back to the main thread to interact with the UI?
For example: after using dispatch_async to interact (maybe the wrong word) with the UI, the app must use performSelectorOnMainThread.
Is that a consideration at all with sendAsynchronousRequest:queue:completionHandler:?
note: I have found similar questions, but not this specifically. eg, in Does NSURLConnection block the main thread? indiekiduk specifically states it is a new thread, albeit an internal one--I think that is flawed, since I thought it was just at the end of the run loop--but I am still learning and probably/possibly wrong.
The documentation for NSURLConnection states for the queue parameter to sendAsynchronousRequest:queue:completionHandler:
queue
The operation queue to which the handler block is dispatched when the request completes or > failed.
The block will execute on whichever thread the passed in queue was set up on.
NSURLConnection sendAsync is scheduled on the RunLoop of the thread its on AFAIK
so the block is called in the thread you start it

Resources