Skip to content
Preptima
hardConceptScenarioMidSeniorStaff

Why does calling .Result or .Wait() on an async method deadlock, and how do you fix it properly?

Blocking on async code with .Result or .Wait can deadlock when the awaited continuation needs the same SynchronizationContext that is blocked. In ASP.NET Core the common failure is thread-pool starvation; the fix is async all the way up.

5 min readUpdated 2026-08-15

Answer

Short answer

Calling .Result or .Wait() on async code can deadlock when the continuation tries to resume on a context that the caller is blocking, such as a UI thread or ASP.NET Framework request context. Prefer await all the way up; in ASP.NET Core, blocking is still dangerous because it can starve the thread pool.

Was this answer helpful?

Likely follow-ups

  • Why does ConfigureAwait(false) have to be applied to every await in the call chain to be effective?
  • What is the difference between .Result and GetAwaiter().GetResult(), and why does neither one solve this?
  • How does the thread pool decide to inject new threads, and why does that make starvation look like a slow leak?
  • When is Task.Run(() => FooAsync()).GetAwaiter().GetResult() a defensible last resort, and what does it cost you?

Related questions

Further reading