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.
Related
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
First of all, I am a a very new Objective C/Cocoa iOS Developer but I've written C/C++ applications before.
So I managed to run the Rabbitmq-c (http://hg.rabbitmq.com/rabbitmq-c/) client inside my iPhone App, and I can connect to Rabbitmq directly from my app and even consume a queue item. So all's good.
Now my problem is, my iPhone app needs to use the rabbitmq-c library to poll for incoming messages in from the server. Probably there will be, an almost infinite while loop.
Do I have to take this to a new thread? Ideally, I want to wrap the rabbitmq-c class as an Async objective C class and use NSNotification (or something similar) to notify my UI. I'm a bit leery of creating a new thread, as I read about stuffs like Runloop etc can solve a lot of problems without using an extra thread.
What is the best way for me to go about this? Any examples of code or directions would be helpful. Please remember, I am not dealing with an Objective C code/Coca rabbitmq library here, I'm using C code inside my iPhone app.
Thanks
Subrat
don't block the main thread with your server polling.
since the operation never ends, create your own thread and run loop for this server polling. you can potentially use the run loop (each thread has one) instead of the infinite while. the alternatives involve regularly spawning threads. it's easiest to just use one thread for this.
once you have an update, post the notification (if you choose NSNotification) from the main thread -- UIKit is meant to operate from the main thread only.
for samples, i'd begin with samples related to NSRunLoop and CFRunLoop.
good luck
You can also create custom delegates for updating the UI, or the stuff related to UIKit.
Notifications might be a little easier to code and offer the advantage that multiple objects can observe one notification. With delegates, such a thing cannot be done without modifying the delegating object (and is unusual).
Some advantages of delegating:
The connection between delegating object and delegate is made clearer, especially if implementing the delegate is mandatory.
If more than one type of message has to be passed from delegatee to delegate, delegating can make this clearer by specifying one delegate method per message.
Or other way is to write method to receive messages. This method can have infinite loop.
Later you can put this method in background thread like this.
[self performSelectorInBackground:#selector(receiveMessages) withObject:nil];
i am getting confused what is the difference between Synchronous NSUrlConnection and ASynchronous NSUrlConnection?is there Synchronous or ASynchronous? if we use detachNewThreadSelector in connectionDidFinishLoading method,is it
ASynchronous NSUrlConnection? which is the best way?any tutorial ...
Synchronous means that you trigger your NSURLConnection request and wait for it to be done.
Asynchronous means that you can trigger the request and do other stuff while NSURLConnection downloads data.
Which is "best"?
Synchronous is very straightforward: you set it up, fire it, and wait for the data to come back. But your application sits there and does nothing until all the data is downloaded, some error occurs, or the request times out. If you're dealing with anything more than a small amount of data, your user will sit there waiting, which will not make for a good user experience.
Asynchronous requires just a little more work, but your user can do other stuff while the request does its thing, which is usually preferable. You set up some delegate methods that let you keep track of data as it comes in, which is useful for tracking download progress. This approach is probably better for most usage cases.
You can do both synchronous and asynchronous requests with NSURLConnection. Apple's documentation provides a clear explanation of the two approaches and delegate methods required for the latter approach.
It seems that you're conflating synchronous/asynchronous connections and threading. In my app I used asynchronous connections as an alternative to threading.
Let's say you want to download a big file without causing the UI to freeze. You have two basic options:
Asynchronous connection. You start with + connectionWithRequest:delegate: (or one of the other non-autorelease options) and it downloads bits of the file, calling your delegate when interesting thing happen. The runloop is still going, so your UI stays responsive. Of course you have to be careful that your delegate don't go out of scope.
Synchronous. You start the connection with + sendSynchronousRequest:returningResponse:error: but the code waits until the download is complete. You'll really need to spawn a new thread (or one of the higher level threading operations that Cocoa supports) or the UI will block.
Which option is "best" or the least painful will depend on the architecture of your application and what you're trying to achieve. If you need to create a thread for a long running process anyway, you might go with the second option. In general I would say the first option is easiest.
It's all pretty well documented on Apple's Developer site.
Something which hasn't been mentioned in the other responses is the size of the request. If you're downloading a large file, for example, then using an asynchronous connection is better. Your delegate will receive blocks of data as they arrive. In comparison, the synchronous method will wait for all the data before making it available to you. The delegate can start processing the response sooner (better user experience), or save save it to a file instead of memory (better resource usage). You also have the option to stop the response without waiting for all the data.
Basically, the asynchronous method gives you more control over the connection but at the cost of complexity. The synchronous method is much simpler, but shouldn't be used on the main UI thread because it blocks.
In response to the other answers regarding the file size: I think file size doesn't matter. If the server responds really slowly and you're loading data synchronous your UI still freezes, even if you're loading a small amount of data, like 3k.
So I'd go for the asynchronous option in every situation, cause you never know what you're going to get with regards to file size, server responsiveness or network speeds.
Is there a way to implement NSURLConnection without it leaking? A number of Apps including NYTimes and others (including mine) suffer from this. Anyone have a working implementation?
It appears that best practice is to use NSURLConnection asynchronously.
According to the documentation, +[NSURLConnection sendSynchronousRequest:returningResponse:error:] is built on top of the asynchronous loading code made available by NSURLConnection. It would not be difficult to reimplement this by spawning and blocking on an NSThread, running the request asynchronously in the background on a run loop and ending the thread once either connectionDidFinishLoading: or connection:didFailWithError: is received.
Of course, you are better off using the asynchronous code in the first place; it makes for a much better user experience
I am trying to work on application in which images should be loaded asynchronously.
Are there any examples related this?
I tried pokeb-asi to understand asynchronous transmission, and it works within that application fine.
But I want to know how to do it from scratch
I am facing following problems.
I don't know the exact way to do it?
what kind of files / frameworks should be added?
The ASIHTTPRequest class is a subclass of NSOperation, so it's typically used by adding the request to either an NSOperationQueue or an ASINetworkQueue. Each request is pulled off the queue, run in a background thread, and then the delegate for that request is notified via a callback method on the main thread.
You could wrap NSURLConnection in an NSOperation and achieve the same thing, however NSURLConnection has an asynchronous API which may suit your needs a bit better.
Try:
http://allseeing-i.com/ASIHTTPRequest/Setup-instructions