Hi. Today i want to p
reach about differentiation. Do you know this dev guy running down the hill, waving his arms, screaming “Aaasync ! Make eeeverything aaasync !” ? I read and discussed about async on the interwebz lately, and was shocked how many guys like the above be out there (insert here a picture of hundreds of that guys, with torches and pitchforks, running down the hill. Yo, frightening).
Since Microsoft (and others) see the immense necessity of good, stalbe and flexible ansynchronous concepts (btw “mission succeeded with an A” at MS), there exists some big async hype in the community. Ok, it´s new (rather not), it´s fine (correct) and you look so damn professional with it (uuum… we come to that one later ^^). So, i´m a developer since nearly 15 years and i often dealing with async concepts, problems and solutions a lot and want to illustrate some things here.
Before we dive deeper into details, here are some common pro´s and con´s of asynchronous programming:
Pro´s:
- Non-Blocking. Resources can be freed. “Can” lead to better use of all resources.
- Enhances all benefits of multicore-architectures to the maximum.
- Has some good “Decoupling”-Effect when used properly.
- Can lead to some good “Don´t think about it, it just works”-Effects.
- Highly required by everything that is communication-based.
- Some scenarios are totally impossible without asynchronous stuff.
Con´s:
- “Can” also lead to a resources-killer scenario.
- Sometimes awful to debug.
- You have to deal a lot more with the words “concurrent”, “tasksafe” and so on.
- Often lead to code fragments/concepts, hard to understand for others/beginners.
- I would say: The human brain works synchronous. Async is “brain-time-consuming”.
- Codeflow is not so “flowy” as in synchronous concepts.
Now i want to take some of the statements and dive into a more detailed view. First: With async/await (or rather the TPL) Microsoft gets out the most of what´s possible and user-friendly when it comes down to async programming. Really. The TPL is a very good piece of software and the guys Stephen Toub and others from the MS Parallels Platform Team are very very clever and did a famous job. But i don´t want to teach you, how good it is, how you use it, when you use it and what can you do with it. There are plenty of good tutorials etc. out there or on StackOverflow, MSDN and so on. Instead i want to sharpen your mind for when, where and why eventually not to use async stuff, or prevent to exaggerate it.
There are many scenarios you would and you should use async. Everytime you really need to “not block” (i.e. UI stuff) you want async programming. That is good, that is fine. But, to start with an example, be aware to not begin at the deepest level (we call it level5 now) of your non-blocking-“module” and make level5 async. Cause, level5 has eventually to do some job, before level4 can start with handling something. With so called “Continuations” you can make level5 async and continue with level4 if it´s done. Fine. There is a very high chance that level3 and level4 have some similar relations. And level3 and level2 also. What you have done at the end, is the following:
You build an asynchronous chain of
level5 -> continuewith -> level4 -> continuewith -> level3 …
At the end of the day, you realize: “My whole module runs async synchronous !”. And that´s… not… good. If you do that often and in many modules, you see that the overall performance won´t be that good, cause of possible context switches, worker threadpool tricks and so on. Also you see, that you have a complex code construct that is a little bit untransparent for others or yourself later in time. But the worst thing is, you loose something but you don´t gain something. But if you code all the “synchronous relations” just synchronous and “only” run the “whole module” asynchronous, this would be way better. There is no need for async, where you don´t need async. The example above is really dull and simple, but believe me, you can entrap yourself in complexity and it can lead you to the scenario above, if you don´t keep your eyes peeled.
The next thing, you have to deal with, is the so called “thread-safe” term. Most of the things you code asynchronous will be consumed. Asynchronous, obviously. So, sooner rather than later, you have to to develop your class, methods etc. thread-safe. You have to deal with Concurrent-Classes, with locks{ }, and primarily with “what happens when this happens and at the same time happens that”-stuff. “Race-conditions” and “soft deadlocks” are also words, that you have to deal with.That can be very fast very horrible to handle. It doesn´t have to, but it can.
When it comes down to such scenarios, you need to debug. But then you will realize that you will never can debug async stuff as good as you could do it with synchronous code. The Visual Studio Debugger is really really great (imho one of or the best out there), but when things happen “parallel” to the timeline, happen not at a concrete time, and when things happen simultaneously, the debug process itself (not the debugger´s abitlity to debug to that point) will always be more difficult. No Debugger ever could improve that to a degree, where it´s the same as debugging synchronous stuff.
So what ? Did that mean you should avoid async ? No. Absolutely not ! Instead you should learn when and how to use async. Don´t run blind down the hill, waving your arms and do, under some circumstances, some unuseful stuff that wastes your time and your developer resources, just for dealing with something you don´t have to. I promised in the intro i came to that point later: So, even if it´s a hype and it´s cool today, do you really think, you look good, when you do things without really know what you are doing ? Or better: When and why you are doing it ?
So, what did we learned ? Do not overdo it ! Differentiate ! (Eventually the TDD-Hardliners hear that and shout back frightened: “If you don´t TDD eeeverything, you will go to hell !”).
Now we can form a rule of thumb here:
“Code synchronous as often as possible and code asynchronous only at and to the concrete point where you really need it.”
“Use async when you can straight handle the stuff that comes along with it, but don´t avoid async for that reasons in general.”
There are so many Discussions along that topic, that i can not link em all. But here is some stuff and some viewpoints, by Stephen Toub and others, to start with:
Have fun.