When it comes to curiousity about inner workings of C# keywords or construct, async and await are at the top of my list by a mile. The amount of complicated intrinsics packed into two simple keywords which magically improve performance by a big margin is absolutely astounding.
However, one of the things I picked up over the years was a saying along the lines of “You should always know what’s going on one or two layers below the abstraction you’re working on.
Therefore, in this post, I’d like to dissect a bit what the async keyword actually does to your code, and potentially also teach you some pitfalls and tricks to use.
The async keyword
In short, the async method allows your method to make use of the async/await paradigm. When using this keyword, your method is required to either return void, Task, Task<T>, a task-like type, or one of the new kids on the block, like ValueTask, IAsyncEnumerable<T> etc.
Also, the await keyword can only be used within async methods.
However, the most significant piece of work connected to the async keyword is the state machine the compiler makes out of it.