OK to launch background threads from other background threads? (NSObj) - iphone

This question is for those of you who, unlike myself, truely understand multi-threading in cocoa apps. Here, briefly, is the situation:
Situation:
My app achieves concurrency by using the methods provided in NSObject. Please tell me if it is OKAY to do the following:
1) My main view controller launches some work in the background to free up the UI:
[self performSelectorInBackground:#selector(loadImages:) withObject:nil];
2) The background work divides its task into several smaller tasks on more background threads so that each task is updated as it finishes (as opposed to when all tasks finish):
[self performSelectorInBackground:#selector(loadOneImage:) withObject:nil];
Rationale:
This was the only way I could invent to get individual tasks (loading/drawing of custom UIViews) in a set to update in UI AS each is completed. Otherwise, all tasks only get updated when the last task in the group has completed...

yes, you may use performSelectorInBackground:... calls to spawn secondary threads from secondary threads.
if you have a lot threads to spawn (in this manner), consider an NSOperationQueue. Otherwise, you may end up with a ton of background threads. 100 threads (for example), each loading one image in a mobile device is not a good use of resources - nor will it be responsive. NSOperationQueue allows you to cap the max number of threads/workers, and reuses worker threads.
note: '100 threads' was used because the number is far beyond logical for the hardware (the question is tagged iPhone). if your image loading is all in memory, just use a serial (1 worker at a time) NSOperationQueue - NSOperations may specify priority. if images are being downloaded, then you may want to stick to 4 or less.
things are different on OS X, where there are more cores and resources available, so these numbers will change as the hardware platform change. on OS X, you can successfully use 100 threads in one app, although it is unusual to need anything near that many threads for most apps.

There's nothing wrong with this approach as far as I can see. According to the doc, performSelectorInBackground:withObject: just spawns another thread and executes your selector there. It doesn't list any limitations. Just don't forget to set up autorelease pools in each method that you call via performSelectorInBackground:withObject: to not leak any memory.

One critical condition you should make sure. Both threads which are running in background should not have any dependency. If they have, then you may end up in inconsistency.
So beter if you go for operation queues rather than spawning thread from another background thread.

Related

Is it sensible to start `CLLocationManager` on a background thread?

According to the documentation of CLLocationManagerDelegate
The methods of your delegate object are called from the thread in which you started the corresponding location services. That thread must itself have an active run loop, like the one found in your application’s main thread.
I am not clear as to whether this means that to receive location manager updates on a background thread, we must instantiate the location manager on that background thread or simply call the startUpdatingLocation() method on that thread.
In any event, this explains an issue when a CLLocationManagerDelegate does not receive any events from a CLLocationManager which was started on a background thread:
That thread must itself have an active run loop
If I understand run loop functioning correctly, all NSThreads are instantiated with a run loop, but the run loop will only be running if you assign some work to the thread. Therefore, to have a CLLocationManager send events correctly on a background thread, we need to set the thread's run loop to loop permanently so that it can process the CLLocationManager's calls as they arrive.
A reasonable solution to making sure the run loop is running is suggested in this question but the author implies that this is a processor expensive way of doing it.
Also, according to the threading documentation,
Threading has a real cost to your program (and the system) in terms of memory use and performance
I appreciate that we are all using lots of threading anyway, by using Grand Central Dispatch, but Grand Central Dispatch probably mitigates a lot of this in its internal thread management.
So my first question is, is it worthwhile setting up a background thread with a continuously running run loop, in order to have location events dealt with on a background thread, or will this involve an unreasonable extra amount of processing when compared to leaving the manager on the main thread?
Secondly, if it is worthwhile, is there a good way to do this using Grand Central Dispatch. As I understand the documentation, Grand Central Dispatch manages its own threads and we have no means of knowing which thread a given block will be executed on. I presume we could simply execute the usual run loop code to make the run loop of whichever thread our CLLocationManager instantiation is run on loop continuously, but might this not then affect other tasks independently assigned to Grand Central Dispatch?
This is a somewhat opinion-based question, but I have a pretty strong opinion on it :D
No.
Just deliver the events to the main queue, and dispatch any work to a background queue if it's non-trivial. Anything else is a lot of complexity for little benefit. CLLocationManager pre-dates GCD, so this was useful information in the days when we occasionally managed run loops by hand and dispatching from one thread to another was a pain. GCD gets rid of most of that, and is absolutely the tool you should use for this. Just let GCD handle it with dispatch_async.
You absolutely should not set up your own NSThread for this kind of thing. They're still necessary at times for interacting with C++, but generally if GCD can handle something, you should let it, and avoid NSThread as much as possible.

iphone - Should I use NSOperationQueue and NSOperation instead of NSThread?

I am facing a design problem of my app.
Basically, the followings are what I am going to do in my app.
A single task is like this:
Read custom object from the underlying CoreData databse
Download a json from a url
Parse the json to update the custom object or create a new one (parsing may take 1 - 3 secs, big data)
Analyse the custom object (some calculations will be involved, may take 1 - 5 sec)
Save the custom object into CoreData database.
There may be a number of tasks being executed concurrently.
The steps within one task obviously are ordered (i.e., without step 2 downloading the json, step 3 cannot continue), but they also can be discrete. I mean, for example, task2's step 4 can be executed before task1's step 3 (if maybe task2's downloading is faster than task1's)
Tasks have priorities. User can start a task with higher priority so all the task's steps will be tried to be executed before all others.
I hope the UI can be responsive as much as possible.
So I was going to creating a NSThread with lowest priority.
I put a custom priority event queue in that thread. Every step of a task becomes an event (work unit). So, for example, step 1 downloading a json becomes an event. After downloading, the event generates another event for step 3 and be put into the queue. every event has its own priority set.
Now I see this article: Concurrency and Application Design. Apple suggests that we Move Away from Threads and use GCD or NSOperation.
I find that NSOperation match my draft design very much. But I have following questions:
In consideration of iPhone/iPad cpu cores, should I just use one NSOperationQueue or create multiple ones?
Will the NSOperationQueue or NSOperation be executed with lowest thread priority? Will the execution affect the UI response (I care because the steps involve computations)?
Can I generate a NSOpeartion from another one and put it to the queue? I don't see a queue property in NSOperation, how do I know the queue?
How do I cooperate NSOperationQueue with CoreData? Each time I access the CoreData, should I create a new context? Will that be expensive?
Each step of a task become a NSOperation, is this design correct?
Thanks
In consideration of iPhone/iPad cpu cores, should I just use one NSOperationQueue or create multiple ones?
Two (CPU, Network+I/O) or Three (CPU, Network, I/O) serial queues should work well for most cases, to keep the app responsive and your programs streaming work by what they are bound to. Of course, you may find another combination/formula works for your particular distribution of work.
Will the NSOperationQueue or NSOperation be executed with lowest thread priority? Will the execution affect the UI response (I care because the steps involve computations)?
Not by default. see -[NSOperation setThreadPriority:] if you want to reduce the priority.
Can I generate a NSOpeartion from another one and put it to the queue? I don't see a queue property in NSOperation, how do I know the queue?
Sure. If you use the serial approach I outlined, locating the correct queue is easy enough -- or you could use an ivar.
How do I cooperate NSOperationQueue with CoreData? Each time I access the CoreData, should I create a new context? Will that be expensive?
(no comment)
Each step of a task become a NSOperation, is this design correct?
Yes - dividing your queues to the resource it is bound to is a good idea.
By the looks, NSOperationQueue is what you're after. You can set the number of concurrent operations to be run at the same time. If using multiple NSOperation, they will all run at the same time ... unless you handle a queue on your own, which will be the same as using NSOperationQueue
Thread priority ... I'm not sure what you mean, but in iOS, the UI drawing, events and user interaction are all run on the main thread. If you are running things on the background thread, the interface will still be responsive, no matter how complicated or cpu-heavy operations you are running
Generating and handling of operations you should do it on the main thread, as it won't take any time, you just run them in a background thread so that your main thread doesn't get locked
CoreData, I haven't worked much with it specifically, but so far every Core~ I've worked with it works perfectly on background threads, so it shouldn't be a problem
As far as design goes, it's just a point of view ... As for me, I would've gone with having one NSOperation per task, and have it handle all the steps. Maybe write callbacks whenever a step is finished if you want to give some feedback or continue with another download or something
The affection of computation when multithreading is not going to be different just because you are using NSThread instead of NSOperation. However keep in mind that must current iOS devices are using dual core processors.
Some of the questions you have are not very specific. You may or may not want to use multiple NSOperationQueue. It all depends on how you want to approach it. if you have different NSOperation subclasses, or different NSBlockOperations, you can manage order of execution by using priorities, or you might want to have different queues for different types of operations (especially when working with serial queues). I personally prefer to use 1 operation queue when dealing with the same type of operation, and have a different operation queue when the operations are not related/dependable. This gives me the flexibility to cancel and stop the operations within a queue based on something happening (network dropping, app going to the background).
I have never found a good reason to add an operation based on something happening during the execution of a current operation. Should you need to do so, you can use NSOperationQueue's class method, currentQueue, which will give you the operation queue in which the current operation is operating.
If you are doing core data work using NSOperation, i would recommend to create a context for each particular operation. Make sure to initialize the context inside the main method, since this is where you are on the right thread of the NSOperation background execution.
You do not necessarily need to have one NSOperation object for each task. You can download the data and parse it inside the NSOperation. You can also do the data download abstractly and do the data manipulation of the content downloaded using the completion block property of NSOperation. This will allow you to use the same object to get the data, but have different data manipulation.
My recommendation would be to read the documentation for NSOperation, NSBlockOperation and NSOperationQueue. Check your current design to see how you can adapt these classes with your current project. I strongly suggest you to go the route of the NSOperation family instead of the NSThread family.
Good luck.
Just to add to #justin's answer
How do I cooperate NSOperationQueue with CoreData? Each time I access
the CoreData, should I create a new context? Will that be expensive?
You should be really careful when using NSOperation with Core Data.
What you always have to remember here is that if you want to run CoreData operations on a separate thread you have to create a new NSManagedObjectContext for that thread, and share the main's Managed Object Context persistant store coordinator (the "main" MOC is the one in the app delegate).
Also, it's very important that the new Managed Object Context for that thread is create from that thread.
So if you plan to use Core Data with NSOperation make sure you initialize the new MOC in NSOperation's main method instead of init.
Here's a really good article about Core Data and threading
Use GCD - its a much better framework than NS*
Keep all your CoreData access on one queue and dispatch_async at the end of your routines to save back to your CoreData database.
If you have a developer account, check this WWDC video out: https://developer.apple.com/videos/wwdc/2012/?id=712

NSTimers VS NSThreading

I'm working on an iPhone Game where the player tilts the iPhone to make the character move, but unfortunately all of the timers I'm using to animate the scenario are slowing down my game. I've been told to use NSThreads, but I really don't know anything about them. My question is, What are the differences between using NSThreads and NSTimers? Or what are the advantages of using NSThreads? How are they useful?
Timers are used for asynchronous, not concurrent, execution of code.
A timer waits until a certain time interval has elapsed and then fires, sending a specified message to a target object. For example, you could create an NSTimer object that sends a message to a window, telling it to update itself after a certain time interval.
Threads are for concurrent execution of code.
An NSThread object controls a thread of execution. Use this class when you want to have an Objective-C method run in its own thread of execution. Threads are especially useful when you need to perform a lengthy task, but don’t want it to block the execution of the rest of the application. In particular, you can use threads to avoid blocking the main thread of the application, which handles user interface and event-related actions. Threads can also be used to divide a large job into several smaller jobs, which can lead to performance increases on multi-core computers.
See also:
How do I use NSTimer?
Timer Programming Topics
Threaded Programming Guide
Timers are objects that simply call methods at a later time. Threads are additional "streams" of stuff to be processed, in psuedo-parallel. It's like comparing apples to oranges—they're not really related. The only relation I can see is if you want to do some processing in the background, but you shouldn't be doing UI calls in background threads, Why are you using timers to make your character move? Knowing that, we might be able to supply an alternate solution.

Implementing multithread using XCode for IPhone

Is there a way implement multi threading in IPhone using xcode? Could you refer me to few tuts that I could use.
Thanks and Regards
Abishek R Srikaanth
The easiest way to implement multi-threading is probably going to be using NSOperationQueue. You subclass NSOperation, or create an NSBlockOperation with the code block you want to run in the background. Set a completion block if you need to be notified on the main thread when the background task finishes. Then add your operation to an NSOperationQueue and you're set! You can also set dependancies on the operation to run a series of events one at a time, or add many operations to the queue if you don't care what order they're executed in.
There are other ways of doing threading, but NSOperation is especially nice since it wraps everything up into a neat unit of work, where you're less likely to make shared memory mistakes, and also you can trust NSOperationQueue to look at the number of cores in your device and do the right thing when it comes to running many operations at once.

NSOperationQueue many threads

In our iPhone application we have several tabs and selecting each tab triggers network connection. In the past we were just detaching new thread for each connection. And after several very quick tab switches application was becoming unresponsive.
Now we decided to use operation queue which supposed should control number of threads and should not allow the application to become unresponsive. But now the app becomes unresponsive even with fewer quick switches (although now it recovers from unresponsiveness quicker).
I ran the app on device from xcode and paused it after several quick switches to see the number of threads. And what I have found is that there are several threads with the following stack:
0 __workq_kernreturn
2 _init_cpu_capabilities
Any idea what are these threads and how to get rid of them?
One of the big benefits of using NSOperationQueue is that you can forget about threads and let the system worry about that for you. It sounds like the root of your problem is that you've got several operations running simultaneously that are no longer needed. Rather than worrying about the specific threads, consider getting those operations to terminate so that they're no longer using up computing resources.
For what it's worth, my guess is that those threads are being managed by Grand Central Dispatch. GCD will create worker threads to process blocks (and operations), and it'll be as efficient as it can about that.
the important part of your problem does not likely lie in the internal/private implementation of worker threads. a good implementation will likely employ a thread pool because creating one thread per operation would cost a lot. operations can reuse and hold on to idle threads.
the important part (likely) lies in your use of the public apis of the implementation you have chosen.
one obvious implementation to support in this case is operation cancellation: -[NSOperation cancel]. when somebody navigates away from a view which has a pending/unfinished request, simply cancel it (unless you'll need the data for caching).
many implementations may also benefit by making requests less often. for example: if your server results only update about once per hour, then it doesn't make sense to request it 'about every minute'.
last point: a connection can use a worker thread itself - check the apis you are using to reduce this if it's a problem.