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.
Related
I have a high-priority audio thread that runs periodically and should do minimal synchronization.
Sometimes the main thread needs to ensure that at least one audio cycle has passed and certain parameters have been picked up, before sending the next batch of parameters. For example, when disabling an audio node the main thread needs to wait until the next cycle when the disabling command is picked up and the node shuts itself down.
At times it is important for the main thread to wait until the command is fully executed, but other times it's not important, so nobody might be listening to the sync event. Hence the "lossy" scenario.
So what is the best way of notifying other threads about an event with minimal overhead and possibly in a "lossy" way?
Can't think of ways of using a semaphore for this task. Are there any canonical ways of achieving this? Looks like Java's notifyAll() works precisely this way, if so, what synchronization mechanism is used behind notifyAll()?
Edit: been thinking, is there such a thing as "send me a semaphore in a queue and I'll signal it"? Seems a bit too complicated but theoretically it could do the job. Any simpler tools for the same task?
As a rule, you never want to block the main thread (or, at least, for more than a few milliseconds). If the response might ever take longer than that, rather than actually waiting, we would adopt asynchronous patterns, let the main thread proceed. Sure, if you need to prevent user interaction, we’d do that, but we wouldn't block the main thread.
The key concern is that if an app blocks the main thread for too long, you have a bad UX (where the app appears to freeze) and you risk having your app killed by the watchdog process. I would therefore not advise using semaphores (or any other similar mechanisms) to have the main thread wait for something from your audio engine controller.
So, for example, let’s say the main thread wants to tell the audio engine to pause playback, but you want the UI to “wait” for it to be acknowledged and handled. Instead of actually waiting, we would set up some asynchronous pattern where the main thread notifies the audio engine that it wants it to pause, the audio controller would then notify the main thread when that request has been processed via some callback mechanism (e.g., via delegate protocol pattern, completion handler closure, etc.). If you happen to need to prevent user interaction during the intervening time, then you’d disable controller and use some UIActivityIndicatorView (i.e., a spinner) or something like that, something that would be removed when the completion handler is called.
Now, you used the term “lossy”, but that generally conveys that you don't mind the request getting lost. But I’m assuming that is not really the case. I'm assuming that you don't really want the request to be lost, but rather only that the main thread doesn't care about the response, confident that the audio controller will get to it when it can. In that case, you'd probably still give this sort of request to the audio controller a callback mechanism, but the main thread just wouldn’t avail itself of it.
Now if you have a sequence of commands that you want the audio engine to process in order, then the audio controller might have a private, internal queue for these requests, where you’d configure it to not start subsequent request(s) until the prior ones finished. The main thread shouldn't be worried about whether the required audio cycle has processed. It should just send whatever requests are appropriate and the audio controller should handle them in the desired order/timing.
I have a complex sync job that does several asyncronous calls for content over HTTP. Each time this content is received, it asks for the next bit and so on. These are all daisey-chained in a big over-all sync job with data on the server.
There are probably 12 steps in this job chain. It seems to get stuck after around the 5th async request, the request never comes back and it hangs for ever waiting for it. I think it may have to do with too many threads being spawned because if I fire off the one it hangs at at the beginning it returns fine.
In the way I imagine it in my head, the main thread asks for async content a. When it comes back in its own asynchronous time it spawns a new thread which then asks for aync content b. When it comes back in its own sweet time it spawns a new thread which then asks for content c. Isn't a new thread being created everytime an async request returns a result?
Am I daisy-chaining these requests right? I was quite good at threads in Java development but I'm a bit confused on how they work in Obj-C. Do I need to use a Thread pool of say 3 threads and reuse these?
Sorry for the high-level question but I'm sure some experts can help clear the cloud of mystery around this.
NSOperationQueues are built on top of Grand Central Dispatch. If you need precise control over order of operations and the ability to dispatch synchronous requests you might want to use GCD directly. Using either, you don't really need to worry about thread creation/management. You simply queue your operations as needed by your app.
The Apple docs are fine on this IMHO but you can find a number of tutorials out there.
[EDIT: added link to Apple docs]
http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html
I have an application that opens a connection with 2 sockets (in and out) and I want to have them working in a thread.
The reason that I want them to be in a separate thread is that I don't want my application to freeze when I receive data, and this can happen anytime as long as the application is running.
Currently I have a class that handle also network communication and I run this class in an NSOperation, I'm not sure if it's the best solution.
I'm not very familiar with threading so guys if you could give me some help I would be very grateful.
Thanks
First, you should know that you can use the same socket to send and receive data — they're generally bi-directional. You should be able to share a reference to the same socket among multiple threads of execution.
Second, unless you'll be receiving large amounts of data and have experienced performance issues with your UI, I would delay optimizing for it. (Don't get me wrong, this is a good consideration, but premature optimization is the root of all evil, and simpler is generally better if it performs adequately.)
Third, NSOperation objects are "single-shot", meaning that once the main method completes, the operation task cannot be used again. This may or may not be conducive to your networking model. You might also look at NSThread. The fact that you already have the functionality "factored out" bodes well for your design, whatever turns out to be best.
Lastly, threading is a complex topic, but a good place to start (especially for Objective-C) is Apple's Threading Programming Guide.
I'm in the design stage for an app which will utilize a REST web service and sort of have a dilemma in as far as using asynchronous vs synchronous vs threading. Here's the scenario.
Say you have three options to drill down into, each one having its own REST-based resource. I can either lazily load each one with a synchronous request, but that'll block the UI and prevent the user from hitting a back navigation button while data is retrieved. This case applies almost anywhere except for when your application requires a login screen. I can't see any reason to use synchronous HTTP requests vs asynchronous because of that reason alone. The only time it makes sense is to have a worker thread make your synchronous request, and notify the main thread when the request is done. This will prevent the block. The question then is bench marking your code and seeing which has more overhead, a threaded synchronous request or an asynchronous request.
The problem with asynchronous requests is you need to either setup a smart notification or delegate system as you can have multiple requests for multiple resources happening at any given time. The other problem with them is if I have a class, say a singleton which is handling all of my data, I can't use asynchronous requests in a getter method. Meaning the following won't go:
- (NSArray *)users {
if(users == nil)
users = do_async_request // NO GOOD
return users;
}
whereas the following:
- (NSArray *)users {
if(users == nil)
users == do_sync_request // OK.
return users;
}
You also might have priority. What I mean by priority is if you look at Apple's Mail application on the iPhone, you'll notice they first suck down your entire POP/IMAP tree before making a second request to retrieve the first 2 lines (the default) of your message.
I suppose my question to you experts is this. When are you using asynchronous, synchronous, threads -- and when are you using either async/sync in a thread? What kind of delegation system do you have setup to know what to do when a async request completes? Are you prioritizing your async requests?
There's a gamut of solutions to this all too common problem. It's simple to hack something out. The problem is, I don't want to hack and I want to have something that's simple and easy to maintain.
I'm not discounting asynchronous delegate calls, but I usually end up using a threaded worker class with synchronous requests. I find it's easier in the long run to have a well defined, threaded API, instead of filling up your controller with code managing the state between asynchronous methods. You could even make asynchronous in your worker thread, although usually it's easier to use the synchronous methods unless they don't support a feature you need to use. Of course, all of this depends on the circumstances, I can think of many situations where simply using the asynchronous methods would be the best route.
Definitely consider NSOperationQueue if you go this route; it greatly simplifies creating multiple worker threads, and it also supports priorities and dependancies between operations. Right now there are some problems with it on 10.5, but I haven't heard of any issues on the iPhone.
An official response is that you should almost always go asynchronous and that synchronous is bad. I found ASIHTTPRequest makes asynchronous requests easy-peasy.
I don't think that there's a "right" answer. It seems that you understand the compromises involved and you just need to make your design around those.
A few extra random points: sometimes your application forces a particular approach. For example, many of the convenience (i.e., synchronous) methods won't allow authentication. For me that meant that my decision was made.
For Yummy I ended up not using threads. I made all my network calls asynchronous and I used the default XML parser (which works using call backs). Since it's all event driven and each unit is small it allows the GUI to be pretty fluid without having the complexity of threading.
I use a state machine to figure out why I'm getting a particular response, and a queue so that I only need to have a single operation "in flight" at any given time. There's a distinct order to most requests so I have no need for a priority system.
The networking code is the most complex in my app and it took a long time to get working much less robust!
I personally look at what is being done, I will ususally use an asyc request to ensure that the UI doesn't block, however, I MAY during the course of that request disable the UI of my application.
A prime example of this is in an application that I built with a "search" button. Once the search was triggered as an async request I would disable the button until the response came back, effectivly limiting the ability for the user to spawn a second asyc request.
Doing this, at least I can prevent the need for priorites, granted this only works if you can in an easy to do way, limit your users to one action at a time.
I'd recommend the asychronous way, no question. Then, load the information only when needed, and use a delegate system to give that information to the correct object.
You don't want to block the UI. Ever. And loading information asynchronously allows you better control over what's happening so you can throw up an error message if needed.
Just a thought: If you want to use the Unit Testing framework for the iPhone, you may want to have synchronous functionality, as that could make writing the tests easier.
However, some of your APIs may not work synchronously, so you need to turn them into sync tasks. Provided the code that performs the unit testing runs in its own thread, you can write a wrapper that will wait until the async task has finished.
To accomplish that, you'd use a semaphore: Your wrapper function starts the async operation and then uses the semaphore to block itself (i.e. puts itself to sleep). The callback that signals the end of the async event releases the semaphore, so that the sleeping wrapper thread can continue and return.
I would use dispatch_async with synchronous. This way, you have the advantage of no delegates/NSNotifications and it is non-blocking
- (NSArray *)users {
if(users == nil) {
users = do_sync_request();
}
return users;
}
// now when calling the users method, do this
- (NSArray *)getUsers {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSArray *users = [self users];
dispatch_sync(dispatch_get_main_queue(), ^{
return users;
}
}
}
Why can't you use an asynchronous request like so:
- (NSArray *)users {
if(users == nil && !didLaunchRequestAlready )
users = do_async_request // Looks good to me
return users;
}
Asynchronous is absolutely the only option - the only real question is if you want to start using separate threads, or if you want to just use the asynch calls. Start there and look at managing threads if you really need to.
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.