I remember when await was introduced into C# – the feature took us away from the callback hell that was developing, but it also required some understanding of the underlying code generation to really see what was going on in simple looking code. The abstraction led to a few rather confusing effects, such as always throwing the first exception of an AggregateException in the await.

At the time people were interested in why you couldn’t use await inside catch or finally blocks, and the answer always came down to confusing semantics. In the recently released C# 6, await is now available in catch and finally blocks, so the question is how this has been achieved without breaking the existing semantics. And I think the answer is that the semantics of some C# forms has now been changed in a way that again requires knowledge of the underlying transforms to understand.

Let’s take the async version of the standard thread abort construct. The call to Abort() notionally throws a ThreadAbortException which can be caught and processed by catch and finally blocks, but which has the interesting semantic of being re-raised when the processing block finishes (unless you reset the abort).

We can explain the behavior of this code fairly easily. The Abort throws the ThreadAbortException, which is caught by the finally block. This finally block prints “Can’t stop me!!” and then the exception is rethrown when the finally block finishes. Hence the “After abort” is never printed.

ie the finally isn’t processed as a CLR finally, but is instead translated to a catch which re-enters the state machine processing. Of course, this means that the ThreadAbort exception which is rethrown at the end of any catch block is going to be rethrown too early, avoiding the exception of the code in the finally block.

I can see that it is a benefit to be able to await in catch and finally blocks, and I guess we’ve had to accept in the past that C# is not the assembly language of .NET. However, the code generation approach to implementing these high level constructs means that sometimes we can see through the abstraction as we can here. I’m not quite sure how important that is.