 <p>I've been using <code>async</code> in production for a couple of years. There are a few core "best practices" that I recommend:</p> <ol> <li><a href="http://nitoprograms.blogspot.com/2012/07/dont-block-on-async-code.html" rel="nofollow">Don't block on <code>async</code> code</a>. Use <code>async</code> "all the way down". (Corollary: prefer <code>async Task</code> to <code>async void</code> unless you <em>have</em> to use <code>async void</code>).</li> <li>Use <code>ConfigureAwait(false)</code> wherever possible in your "library" methods.</li> </ol> <p>You've already figured out the "<code>async</code> all the way down" part, and you're at the point that <code>ConfigureAwait(false)</code> becomes useful.</p> <p>Say you have an <code>async</code> method <code>A</code> that calls another <code>async</code> method <code>B</code>. <code>A</code> updates the UI with the results of <code>B</code>, but <code>B</code> doesn't depend on the UI. So we have:</p> <pre><code>async Task A() { var result = await B(); myUIElement.Text = result; } async Task&lt;string&gt; B() { var rawString = await SomeOtherStuff(); var result = DoProcessingOnRawString(rawString); return result; } </code></pre> <p>In this example, I would call <code>B</code> a "library" method since it doesn't really need to run in the UI context. Right now, <code>B</code> <em>does</em> run in the UI thread, so <code>DoProcessingOnRawString</code> is causing responsiveness issues.</p> <p>So, add a <code>ConfigureAwait(false)</code> to every <code>await</code> in <code>B</code>:</p> <pre><code>async Task&lt;string&gt; B() { var rawString = await SomeOtherStuff().ConfigureAwait(false); var result = DoProcessingOnRawString(rawString); return result; } </code></pre> <p>Now, when <code>B</code> resumes after <code>await</code>ing <code>SomeOtherStuff</code> (assuming it did actually have to <code>await</code>), it will resume on a thread pool thread instead of the UI context. When <code>B</code> completes, even though it's running on the thread pool, <code>A</code> will resume on the UI context.</p> <p>You can't add <code>ConfigureAwait(false)</code> to <code>A</code> because <code>A</code> depends on the UI context.</p> <p>You also have the option of explicitly queueing tasks to the thread pool (<code>await Task.Run(..)</code>), and you <em>should</em> do this if you have particular CPU-intensive functionality. But if your performance is suffering from "thousands of paper cuts", you can use <code>ConfigureAwait(false)</code> to offload a lot of the <code>async</code> "housekeeping" onto the thread pool.</p> <p>You may find my <a href="http://nitoprograms.blogspot.com/2012/02/async-and-await.html" rel="nofollow">intro post helpful</a> (it goes into more of the "why's"), and the <a href="http://blogs.msdn.com/b/pfxteam/archive/2012/04/12/10293335.aspx" rel="nofollow"><code>async</code> FAQ</a> also has lots of great references.</p>