The previous section discussed how successful completion of an asynchronous method is handled based on a translation of
return statements into method calls that cause the returned task’s
Result to get set. Under the hood, this is fueled by a builder object that acts as a proxy to a
TaskCompletionSource<T> object, which on its own turns proxies into the returned task object.
However, a method can return to its caller in another way, too, namely when an exception occurs. In regular methods, this is achieved by unwinding the call stack and using techniques like structured exception handling (SEH) that are built in to the operating system and the runtime. When dealing with asynchronous methods, though, there’s no such thing ...