 <p>Just to add to the accepted answer (not enough rep to comment), I had this issue arise when blocking using <code>task.Result</code>, event though every <code>await</code> below it had <code>ConfigureAwait(false)</code>, as in this example:</p> <pre><code>public Foo GetFooSynchronous() { var foo = new Foo(); foo.Info = GetInfoAsync.Result; // often deadlocks in ASP.NET return foo; } private async Task&lt;string&gt; GetInfoAsync() { return await ExternalLibraryStringAsync().ConfigureAwait(false); } </code></pre> <p>The issue actually lay with the external library code. The async library method tried to continue in the calling sync context, no matter how I configured the await, leading to deadlock.</p> <p>Thus, the answer was to roll my own version of the external library code <code>ExternalLibraryStringAsync</code>, so that it would have the desired continuation properties.</p> <p><hr> <strong>wrong answer for historical purposes</strong></p> <p>After much pain and anguish, I found the solution <a href="http://weblogs.asp.net/pglavich/asp-net-web-api-request-response-usage-logging" rel="nofollow">buried in this blog post</a> (Ctrl-f for 'deadlock'). It revolves around using <code>task.ContinueWith</code>, instead of the bare <code>task.Result</code>.</p> <p>Previously deadlocking example:</p> <pre><code>public Foo GetFooSynchronous() { var foo = new Foo(); foo.Info = GetInfoAsync.Result; // often deadlocks in ASP.NET return foo; } private async Task&lt;string&gt; GetInfoAsync() { return await ExternalLibraryStringAsync().ConfigureAwait(false); } </code></pre> <p>Avoid the deadlock like this:</p> <pre><code>public Foo GetFooSynchronous { var foo = new Foo(); GetInfoAsync() // ContinueWith doesn't run until the task is complete .ContinueWith(task =&gt; foo.Info = task.Result); return foo; } private async Task&lt;string&gt; GetInfoAsync { return await ExternalLibraryStringAsync().ConfigureAwait(false); } </code></pre>