async/await syntax should be used for I/O bound asynchronous operations only.
public async Task<int> GetUrlContentLengthAsync()
{
    var client = new HttpClient();
    Task<string> getStringTask =
        client.GetStringAsync("https://docs.microsoft.com/dotnet");
    DoIndependentWork();
    string contents = await getStringTask;
    return contents.Length;
}
Compiler transforms code into a state machine that to track yielding execution for await and resuming execution when a background job is finished.
Things to keep in mind:
- asyncmethod needs await
- add Asyncsuffix to asynchronous methods
- async voidfor ‘Fire and Forget’ work i.e. event Handlers
- be aware of mixing LINQ with asynclambdas
- wait for tasks in a non-blocking manner (do not use Task.Resulti.e.)
- for tight loops use ValueTasks
- Consider using ConfigureAwait(false)for performance and for avoiding deadlocks
Further read:

