Formal definition of async deadlocks
You are susceptible to deadlocks if: 1. 2.
You have a current SynchronizationContext that enforces exclusive access; Some code further into your call stack has access to it and can/does: a. Synchronously block on some async code; b. Within that async code awaits an incomplete task that does not use .ConfigureAwait(false), or temporarily removes the context.
If you use .Result, .Wait(), .GetAwaiter().GetResult() you have done a dangerous thing, and you should be prepared to guard against naughty awaiters (you may not even control).