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 ?
views:
102answers:
6Why is the Asynchronous mode is better than the Synchronous one when handling clients requests ?
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
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).
You don't want to block the UI. With asynchronous operation you can do other things while waiting for the server to respond.
Asynchronous mode lets you continue processing while synchronous mode makes you wait.
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.
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.