Best practice: NSURLConnection sendSynchronousRequest vs sendAsynchronousRequest - objective-c

Is it best to send a synchronous or an asynchronous request?
I'm sending a request to a server, asking for a list of files, which I would like the user to choose from.

Synchronous request does stop the application from any user action until it completes, because it runs in the main thread.
Asynchronous does not as it runs in other thread.

You should always use asynchronous requests as they do not block the thread they are called from. Instead they will call your delegate methods when the connection fails or succeeds. If you need to prevent the user from doing anything while the connection is running, use a HUD class like MBProgressHUD (check github).

You'd want to use asynchronous calls when you're calling from the Main Thread. Otherwise, the whole user interface will become unresponsive (i.e: freeze) until the server responds. (The user interface in maintained by the main thread).
You'd want to use synchronous calls when you're calling from another thread and you want it to wait until it has the response before continuing. If you've manually created a thread, calling asynchronous from this new thread would create a third thread.
Asynchronous means the "calling body" won't wait until the task is done.

Related

Is there a way to update GUI or use GUI while CPU is working?

The GUI of my program freezes while the program is doing its work. I created a mass import which can send X-thousand datarows via a called webservice into a database. The code is already very big and I cannot rewrite it for multithreading purpose.
I don't know how to do it. Any suggestions? If needed I will show some code, but at the moment I don't know what to show.
Firstly, you should rewrite it to use avoid synchronously doing this on the UI thread. If you do a lot of work on the UI thread, it simply will freeze the UI thread. There are a few options here:
If your web service proxy supports asynchronous calls, and if you're using VB 11, you can use Async / Await to call the web service asynchronously from the UI thread in an asynchronous method, and control will return back to the UI thread at the same point in the asynchronous method when the call has completed. It takes a little while to get your head round asynchrony, but this is probably the best option if it's possible.
You can use the Task Parallel Library to make calls on a different thread, but then you'll need to think carefully about how that thread is going to interact with your UI thread.
You can use BackgroundWorker to run some code on another thread, but report progress and completion back on the UI thread
You could potentially call Application.DoEvents between each web service call, to let the UI handle events. This is dangerous - it can lead to re-entrant code, so locks won't behave as you expect them to, and similar hard-to-diagnose errors. This should be your last option, if all else fails.

performSelector:OnThread:waitUntilDone not executing the selector all the time

I have an app where the network activity is done in its separate thread (and the network thread continuously gets data from the server and updates the display - the display calls are made back on the main thread). When the user logs out, the main thread calls a disconnect method on the network thread as follows:
[self performSelector:#selector(disconnectWithErrorOnNetworkThread:) onThread:nThread withObject:e waitUntilDone:YES];
This selector gets called most of the time and everything works fine. However, there are times (maybe 2 out of ten times) that this call never returns (in other words the selector never gets executed) and the thread and the app just hang. Anyone know why performSelector is behaving erratically?
Please note that I need to wait until the call gets executed, that's why waitUntilDone is YES, so changing that to NO is not an option for me. Also the network thread has its run loop running (I explicitly start it when the thread is created).
Please also note that due to the continuous nature of the data transfer, I need to explicitly use NSThreads and not GCD or Operations queues.
That'll hang if:
it is attempting to perform a selector on the same thread the method was called from
the call to perform the selector is to a thread from which a synchronous call was made that triggered the perform selector
When your program is hung, have a look at the backtraces of all threads.
Note that when implementing any kind of networking concurrency, it is generally really bad to have synchronous calls from the networking code into the UI layers or onto other threads. The networking thread needs to be very responsive and, thus, just like blocking the main thread is bad, anything that can block the networking thread is a bad, too.
Note also that some APIs with callbacks don't necessarily guarantee which thread the callback will be delivered on. This can lead to intermittent lockups, as described.
Finally, don't do any active polling. Your networking thread should be fully quiescent unless some event arrives. Any kind of looped polling is bad for battery life and responsiveness.

Cancelling sendAsynchronous request

I am using sendAsynchronous request to receive data from multiple request at same time. It works great, i am able to load all the data. Even it is faster. But i want to cancel my request if the user cancels the request. so i have created a NSThread and using that thread i have created asynchronous request. When user clicks cancel button i just cancelled the thread.
But even after cancelling the thread the data is still getting loaded. So i want to stop those requests completely from loading data.
Even i used this,
[NSObject cancelPreviousPerformRequestsWithTarget:(id) selector:(selector) object:(id)]
but it doesn't work. Any help or suggestion will be appreciated.
Thanks in advance.
According to the documentation the NSUrlConnection class has it's own cancel method.
Note: Why are you using sendAsynchronousRequest in a own thread? The completion-handler will be executed when the request returns. While the request tries to reach the server and get an answer the main-thread shouldn't be blocked. I suggest to use either a synchronous request in a background thread or an asynchronous request in your main thread.
Also be aware, that your thread doesn't terminate just by calling [NSThread cancel]

Triggering via Asynchronous Callbacks

If an application executes a code block asynchronously and notifies the completion state in a callback, do these all leave execution on the main thread (the callback)?
What is the correct way to handle Core Graphics drawing and file operations in this callback?
I currently have these instructions running in the callback, but would like to trigger a thread to handle these instructions instead.
If you are doing any UI drawing, that has to be on the main thread. If you hvae these asynchronous blocks doing work now (ostensibly in a concurrent dispatch queue), why not just do all the work there, and when you have a finished product to show, only then message back on the main block. If your callback calls other methods in your class, the safest way to deal with concurrency is to define helper objects - small objects that take some input and product an output.
Create the helper, attach whatever data it needs, kick it off in a block on a queue, and when its done it messages back on the main thread that extracts the finished product, renders it, then deletes the helper object.
I dont have much experience in Core Graphics, but I've done a good amount of work on blocks.
In my opinion, if your application executes a code block asynchronously (on a new thread), then it's a good practice to the make callback or notification on the main thread.

WCF client deadlocking due to callback even when callback IsOneWay

new to WCF.
I have a client which is deadlocking when calling a WCF service.
The service will invoke a callback to the client at the time of the call which is marked as IsOneWay. I have confirmed that the service is not blocking on the callback.
The client then immediately calls the same service again (in a tight loop), without having yet serviced the callback. The client then deadlocks (and a breakpoint on the service side never gets triggered).
So to recap:
CLIENT SERVICE
Call service -----------------------> (service breakpoint triggers)
(waiting for dispatch thread) <------ Invoke callback (IsOneWay - doesn't block)
Service returns
Call service again immediately -----? (service breakpoint doesn't trigger)
(deadlock)
I am assuming that the callback has grabbed some WCF lock at the client end, and then the second service call from the client also wants that lock, so deadlock results. But this is just assumption.
I have read about ConcurrencyMode but I can't decide which mode to use, or where to put it because I'm not 100% clear on what is going on, and what is being blocked exactly.
I would also prefer to keep all callbacks being serviced by the dispatch thread if possible as it keeps the code simpler.
Can any WCF experts shed light on exactly what is going on here?
Many thanks
OK, think I've sussed it.
WCF services default to single threaded. All calls and callbacks get marshalled to a single thread (or SynchronizationContext to be more accurate).
My app is a single threaded WPF app, so the SynchronizationContext gets set to the dispatch thread.
When the callback comes in it tries to marshal the call to the dispatch thread, which of course is sat blocking on the original service call. I'm not clear it locks exactly, but there's obviously some global lock that it tries to get before waiting for the dispatch thread.
When the dispatch thread then calls the service again, it deadlocks on this global lock.
Two ways around it:
1) Create the service proxy on a different thread in the first place. All calls will get marshalled through this thread instead and it won't matter that the dispatch thread is blocked.
2) Apply [CallbackBehavior(UseSynchronizationContext = false)] attribute to the client class that implements the callback. This means WCF will ignore the synchronisation context when the callback comes in, and it will service it on any available thread.
I went with 2. Obviously this means I need to marshal callbacks that could update the GUI to the dispatch thread myself, but luckily my callback implementation is a small wrapper anyway, so I just do a _dispatcher.BeginInvoke() in each callback method to marshal ASYNCHRONOUSLY. The dispatch thread will then service when it gets a chance which is what I wanted in the first place.
The sequence that you have depicted resembles a synchronous call. While in an async call, the sequence would be:
Client Server
Call service --------------->ProcessRequest(1) //Your for loop for instance.
Call service --------------->ProcessRequest(2)
Call service --------------->ProcessRequest(3)
Call service --------------->ProcessRequest(4)
Call service --------------->ProcessRequest(5)
Callback awake <---------------Response1 //Responses tends to pour in...
Callback awake <---------------Response2
Callback awake <---------------Response3
Callback awake <---------------Response4...
In each case of each async web service call, the system creates a separate IO thread(IOCP thread), and processes the request. In this, seldom you will find a deadlock.
I have found this way, even when called within a loop, to be working very well.
You can, for instance, register for the event .OnProcessComplete, and then call the ProcessCompleteAsync method.