, exoteric wrote

There are many nice acronyms but few nice technologies.

APM is pretty horrible to work with in my oppinion. Rx has methods to encapsulate the pattern so that it becomes practical and usable. EAP is probably better but it doesn't look all that attractive or compositional either.

There are several ugly ways to skin a cat - I'm just trying to find the cleanest one - to use a slightly disguisting metaphor.

I find Rx quite superior but it could benefit from some kind of language support. F# provides a means to customize semantics of existing syntactic constructs and override the semantics. It doesn't quite feel like the optimal solution yet though (dealing with side-effects, and how to best use multiple interpretations of a for loop inside a workflow body, for example).

Rx is more general than async/await and therefore has more applications.  Rx doesn't force you to decide if something is async or sync in advance.  The composition is the same regardless.  Rx applies to single or multi-values, and therefore has more power than async/await as it does not deal with mult-values. 

Rx shares the same pattern across many languages.  Async/await does not.  You can use Rx from any .NET language.  You can use Rx in JavaScript and the semantics and everything you learn about Rx from .NET applies to it except the specialized schedulers which vary depending on the implementation.   Learning Rx means you will be able to leverage it in any language (eventually) and also deal with asynchrony in any language - even C/C++ are getting Rx.  F# and Rx work very well together and show how simple Rx could be with language support. 

The complexity of Rx scales very well, because you can guarantee composability and you cannot do that with APM/TPM - you simply cannot because it's not obeying the fundamental rules of composition. Rx is built on mathematical rules of composition which can be expressed in many languages and there's no escaping having to understand these laws of composition for a programmer today.  You must understand these at some point to deal with complexity. 

The limitations of C# is the problem with Rx, not Rx, in terms of complexity, as managing continuations seems to be a problem for large Rx compositions, as the number of arguments grows.  The code is inside out, but this is a simple matter of experience to grok, and everyone is capable.  There is also so many ways to write a complex composition in Rx that one can write horribly unreadable code in Rx which once refactored becomes a beautiful pearl.  There are code samples that show how Rx on the server can communicate with the client in just an absolutely simple pattern of LINQ queries, everywhere.

But what can I say, without code to back it all up?  Later, after work, I'll try to post a few examples of crappy Rx code versus beautiful Rx code and then perhaps we can really see where the complexity lies, and why Rx has this real/perceived level of difficultly that is a barrier to entry.