how to prevent main thread ios from killing background thread - ios

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.

Related

Scheduling execution of blocks in Objective C

I'm creating an application in objective C where I have two threads:
The main thread, which is woken up from sleep and is called into asynchronously by a module above it
The callback block(thread) whose execution is asynchronous and is dependent on an external module "M" sending a notification.
On my main thread, I want to wait for the callback to come in before I start doing my tasks. So, I tried using dispatch_group_enter and dispatch_group_wait(FOREVER) on the main thread while calling into dispatch_group_leave on the callback thread. This ensured that when the main thread is the first to execute, things happen as they are supposed to, i.e the main thread waits for the callback to come in and unblock it before performing its tasks.
However, I'm seeing a race condition where the callback block gets called first sometimes and is stuck on dispatch_group_leave (since at this point the main thread has not called into dispatch_group_enter.
Is there a different GCD construct I can use for this purpose?
The “main thread” is a thread which handles UI, system events, notifications, etc. We never block that thread. Blocking it results in a horrible UX where the app will appear to freeze and your app may even be terminated by the “watch dog” process, which kills apps that it thinks are frozen. In some cases, the app will deadlock.
So, if you really mean “main thread”, then the answer is that you would never “wait” on that thread (or otherwise block it). The pattern is to have your background thread do what it needs, and then dispatch model/UI updates back to the main thread with GCD (or submit your notification and let the main thread process it).
If you want a UX where the user is not allowed to interact with the UI while this background process is underway, you would present something in your UI that makes that clear. A common pattern is a dimming/blurring view that covers the whole view, often with a UIActivityIndicatorView (i.e., a spinner), and when the task dispatched to the background queue is done (or have the notification handler do that), you’d then remove that dimming/blurred view and the spinner and update the UI accordingly.
But you never block the main thread by waiting.

Clear process flow of NSRunLoop

Digging more than one day....Apple, Google, Slideshare and stackoverflow. But still not clear about NSRunLoop.
Every thread has a runloop by default.Application mainThread has mainRunLoop.
1. If MainRunLoop get input events is it creating new thread to execute it? Then another runLoop created? How then multiple thread and multiple runLoop work? Communicate?
2. If runLoop has no input event/task it sleeps.When a RunLoop ends?
3. Why i should care about runLoop?
4. Where i can use it?
Where i miss that i can't understand the life cycle?
Lets look on your`s list:
Wrong. Threads do not have built-in runloop. They need to be created manually.
Runloop doesn`t create another threads, its immediately executes an event. That is why at the main thread we can see locked interface - by heavy-load tasks in the main thread (UI in iPhone runs on the main thread). Runloops can communicate with each other with the help of mac ports.
Runloop sleeps before the first event come, then wakes up and ends. Only exception - timer, but it will not runloop. Runloop need to start run every time after Event (in the loop). If you call the run, there is already a built-in loop.
Can use to create some threads which must track or execute something periodically. For example, you can create a thread, when runloop for it and then other threads can execute it`s selectors through performSelector. This creates a background query processor, which does not require each time to create a new thread.

Will a background thread that receives a return eventually close itself?

It looks like if a background thread is running when you hit the home button, things are suspended and then resumed when reopening the app. I simply want things to stop when the home button is pressed so that on resume, the user can start things from the beginning. After doing some research, it looks like a simple bool flag to periodically check is the way to go. My question, is the part after that. I have the flag part working using some of the notifications like UIApplicationWillResignActiveNotification, but my question is what action to take to actually stop things. I can do a simple return to stop things, but how does that affect the thread itself? As a general question, if nothing is running, or it gets to the end of the code, will the thread close itself? Or is some sort of explicit exit call needed? In my rough testing, that thread seems to go away, but I wasn't sure.
If you have a thread whose entry point returns, your thread will close. If you install a runloop, your thread may never close, depending on your implementation. In any case, when an app enters background, the main thread is allowed to complete the current runloop run and then the app is suspended. All other threads are suspended also. Once your app returns to the foreground, or when woken up in the background under certain circumstances, your thread will resume work until you end the entry point, suspend it or your app is suspended again.
This is a simplification, of course. In some instances, threads are reused, even if your provided entry point returns. This is the case of thread pools, GCD, etc. In these cases, a thread may appear as alive, but it is actually suspended and takes little resources.

concurrent NSOperation, why start on main thread?

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.

Perform selector just after application:didFinishLaunchingWithOptions?

I need to upload some left-over data to server in application:didFinishLaunchingWithOptions, but it takes some time and eventually the app may be killed as it cannot finish launching in time, so I used:
[myObject performSelector:withObject:afterDelay:]
with 0.2f delay, to let application:didFinishLaunchingWithOptions finish, but it does not look like a good idea, so I wonder is there a way I can perform the selector just after application:didFinishLaunchingWithOptions?
I know there are applicationDidBecomeActive but I need it to be executed in application:didFinishLaunchingWithOptions.
If you use a delay of 0, it will be executed as soon as control returns to the runloop.
However, if this is blocking for too long in appDidFinishLaunching, then it will also block no matter when you run it. You really should move this code to a background thread. Synchronous network access on the main thread is never a good idea.

Resources