views:

102

answers:

6

I have a client-server project and was searching for the better way to handle the requests from the clients so some people adviced that the Asynchronous mode is better than the synchronous one and the thread pool mode.
My question is why ? and is there a disadvantages in the Asynchronous mode ?

+1  A: 

One disadvantage of synchronous operations is IMO that you can't interrupt them - e.g. when your server application calls synchronous method WaitForConnection() and no client connects, you can't stop waiting...

For instance try to look at this http://stackoverflow.com/questions/607872/what-is-a-good-way-to-shutdown-threads-blocked-on-namedpipeserverwaitforconnecti

Ondra C.
A: 

In a synchronous server you've to handle locks when accessing your data structures (if updates are present) and this takes time and code (and is a source of hard to find bugs). Also having many (e.g. thousands) threads poses technical problems in many implementations (e.g. for stack allocation) and if the server is IO bound those threads are almost all sleeping (waiting for network) and just wasting memory.

Using the asynchronous model on a single thread you can ignore the locking problem (this means your processing is as fast as it can get) and you use only the memory actually needed for the clients (there is only one stack).

However now multicore machines are quite common so part of the advantage is lost (because you've to lock if modifying a shared data structure). Probably best efficiency can be get using a balancer in front of N asynchronous servers where N is the optimal number of threads for your environment.

The bad side of asynchronous approach is that depending on your tools the code can be quite ugly and hard to understand, and that if computation is not trivial and by mistake your processing enters an endless loop the whole asynchronous server will be unresponsive (so probably a watchdog should be added).

6502
Asynchronous does not solve the locking problem. You're async callbacks can be re-entered by multiple callbacks on different threads. You still need to protect any shared state when using the async model.
heavyd
The problem with coding correct locking with preemptive multithreading is that switching is "invisible" and can occur at any time.Switching points in an asynchronous implementation are fixed and normally absolutely evident. Also debugging is much simpler because of determinism.While there can be still some form of "logical" locking this is in my opinion nothing compared to the difficulty to get locking right in a shared data update approach.
6502
@heavyd: Re-reading your comment seems to me there is a problem with terminology. I said that with single-threaded asynchronous implementation you can forget about the locking problem... (meaning with that about physical locking for concurrent access, not logical locking between state changes of the automata that of course is mandatory) and also that if asynchronous is not coupled with single-threaded then this advantage is lost.In your comment you talk about different threads so there is probably some misunderstanding about the terms.
6502
+1  A: 

You don't want to block the UI. With asynchronous operation you can do other things while waiting for the server to respond.

chum of chance
+1  A: 

Asynchronous mode lets you continue processing while synchronous mode makes you wait.

P.Brian.Mackey
+5  A: 

Yes, asynchronous requests can often be handled without the expense of a thread. The operating system has special support for them, features like overlapped I/O and completion ports. What they essentially do is leverage the expense of a kernel thread, one that's needed anyway because a driver needs to be able to handle multiple requests from multiple user mode programs. The .NET framework readily takes advantage of that in its BeginXxx() methods.

Using threadpool threads is cheap too, but you are subject to the behavior of the threadpool scheduler. Which doesn't much like starting more TP threads then there are cores. TP threads should never be used for code that can stay blocked for a while, pretty typical for CS tasks like making a connection.

Error handling is very difficult in asynchronous code. You typically have very little context when the EndXxxx() method raises an exception. It happens on a callback thread, very far away from the main logic. Okay when you can shrug "didn't happen, lets log it", total bedlam and redrum when the program's state depends on it. Always choose synchronous mode in the latter case.

Hans Passant
+1 And they're even better than that: often no kernel thread is needed (most drivers do not even have threads).
Stephen Cleary
+1 vrey useful answer.Deep thanks!
M.H
+1  A: 

To "tag along" with Hans' answer: the independence of I/O operations from threads allows much more significant scaling; tens of thousands of outstanding requests are possible, which simply cannot be done using threads.

Also, when you start considering the complexities of error handling in protocol design, it turns out that the complexity of asynchronous methods are much less than the complexity of correctly writing synchronous code. Most synchronous socket code appears simpler but in fact contains subtle bugs.

Asynchronous methods are also important to prevent deadlock situations if both sides send more data than they read; see this blog post for more discussion.

If you'd like the reliability benefits and (most of) the performance benefits of asynchronous I/O in a thread-safe wrapper (with simpler error handling), consider the Nito.Async library.

Stephen Cleary