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.
Related
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
Need your help.
In my application, i want to implement a background process which keeps running continuously and downloads the updated data and stores it in document folder.
And my main thread should keep checking the document folder and display the updated data in view control.
The child thread should end once the view disappears. and start again once the view appears.
What is the best way to do it? NSThread or NSOperationQueue? What precautions are required?
I also have to access few variables of the class. So is should be thread safe.
Thanks in advance.
Regards
If you do not need to update a progress bar or something in iOS5 there is one great API method + sendAsynchronousRequest:queue:completionHandler: that allows you to run async download as a block inside NSOperationQueue. If not you should look into third party libs such as ASIHTTP request or https://github.com/AFNetworking/AFNetworking(probably better the last one) or you need to build you own download manager, not a simple task
there are two ways to do it..
First: You use NSOperationQueue which is a bit bulkier as it is build on GCD but does have some extra features.
Second: You use GCD (grand central dispatch) looking at requirements I would say GCD seems fine as you can easily access any thread(main or background) this would be slightly quicker.
You can have a look at - (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg This method creates a new thread in your application, putting your application into multithreaded mode if it was not already. In your viewDidDisappear, you can stop the task when your view disappears
From Apple Docs. Apple encourages to investigate the alternative Mac OS X technologies for implementing concurrency. This is especially true if you are not already familiar with the design techniques needed to implement a threaded application. These alternative technologies simplify the amount of work you have to do to implement concurrent paths of execution and offer much better performance than traditional threads.
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/AboutThreads/AboutThreads.html#//apple_ref/doc/uid/10000057i-CH6-SW2
I'm confused about the concept of "threads" in iPhone development:
Why are threads necessary / useful?
How can threads be used in Objective-C?
You need multi-threading in objective c because sometimes you need functions/code to run "in the background" (read: on another thread). For instance (but not explicitly) you might need to download large amounts of data off the internet (a picture, or a video).
In this case running the download on the 'main' thread will cause the iphone to freeze before the download is complete. So you use multi-threading to download the data AND let the iphone work all at the same time.
There are lots of ways to do multithreading in objective-c. To be honest you need to look it up yourself, we're not here to just spoonfeed you.
Things to look up are: NSURLConnection and the method [self performSelector:onThread:...]
More simple...If you want to run some methods(processes) parallely you can use threads...One thread is doing one stuff while another doing other stuff... So u can use threads if you need something to be done when another thing is doing...
Example: Thread 1: sending request to server
Thread 2: preparing information(image,text etc) to be sent.
So in general this is the purpose of threads
Recently, Apple suggests that programmers should move away from thread and use an alternative solution with more advantages, better performances and much more easier to implement; it's Concurrency Programming:
http://developer.apple.com/library/mac/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008091
The recommended way to implement concurrency is using queues.
For those who just want to execute a method / block in a separate thread - use this code:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
[self longMehtod];
});
for further information read the Concurrency Programming Guide from Apple
How would you guys go about creating online play capabilities for an iPhone game? Obviously, one could poll the server every so often, but is this realistic given the capabilities of the device? Assume you're polling the server every second or two and retrieving 100 bytes of data... Is it possible to retrieve the data in the background while gameplay continues or is it going to be held up by the server poll?
Thanks in advance,
BCH
You need to make a multithreaded application. Then you can have a background thread polling the server (or better, making asynchronous requests on it.
Have a look at the NSOperation and NSOperationQueue classes. You'll make each background task be represented by an instance of an NSOperation class. This class takes care of starting the operations, making sure that they are run in the appropriate order, and accounting for any priorities that you set.
The most common way to use NSOperation is to write a custom subclass and override the method, main. The main method gets called to perform the operation when the NSOperationQueue schedules it to run.
If you don't want the overhead of subclassing, take a look at the NSInvocationOperation class. This is a concrete subclass of NSOperation that makes it easy to attach an operation to an existing method. NSInvocationOperation objects can be added to an NSOperationQueue (just like NSOperations), so that you get multi-threading without having to subclass.
You can do asynchromous requests. But you are asking a really, really hard question here. Just want to make sure you know that.
Take a look at the WiTap example (in xcode do a full text search for witap). It uses NSStreams to get asynchronous behavior without you having to resort to managing your own threads or poll.
Use OpenFeint.. It allows you to develop Over the internet worldwide non real time turn based multiplayer games easily..
I'm not sure if GameCenter now supports similar functions.
I have some slow internet task to save and load file, I'd like to do those slow tasks in some background thread. I am wondering whether that's doable, and if it is, any sample code?
Then after it is finished, I'd like it to notice back to the main thread, so that I could update the UI.
Take a look at NSURLConnection. It will load an NSURL (using NSURLRequest) in the background, and send delegate methods regarding its status.
Ultimately the device you are running your code on has a single processor and cannot possibly load large quantities (gigabytes) of data. The best route, by is likely that suggested by Ben (NSURLConnection asynchronously) which gives you the added advantage of being able to cleanly cancel and handle error messages. While it isn't technically threaded in the way you probably think you want it to be, it is well integrated with the event loop and is non-blocking. If that is still not enough, I would suggest looking at NSOperation and NSOperationQueue. You can fire off an NSOperation sub-class object and perform the download there (I would still advise doing it asynchronously there so as to enable canceling, pausing, etc).
Log in to the iPhone Developer Center and search for Introduction to Threading Programming. Or, maybe you can log in and use this link:
http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/Multithreading/Introduction/chapter_1_section_1.html#//apple_ref/doc/uid/10000057i-CH1-SW1
If you do decide you need a background thread even after using asynchronous HTTP calls to gather the data, don't forget to wrap the background thread code in a new NSAutoReelasePool and then release it at the end.