试图了解我什么时候应该使用ConfigureAwait(). 
根据书:
当一个
async方法在等待后恢复时,默认情况下它将在相同的上下文中恢复执行。如果该上下文是 UI 上下文并且大量异步方法在 UI 上下文上恢复,则这可能会导致性能问题。
解决方案
为避免在上下文中恢复,请等待结果ConfigureAwait()并为其continueOnCapturedContext参数传递 false :
async Task ResumeWithoutContextAsync()
{
    await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
    //This method discards its context when it resumes.
}
什么是上下文以及如何查看ConfigureAwait()示例应用程序中的变化:
static async Task ResumeWithoutContextAsync()
{
    await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(true);
    Console.WriteLine("ManagedThreadId {0}", Thread.CurrentThread.ManagedThreadId);
    //This method discards its context when it resumes.
}
static void Main(string[] args)
{
    ResumeWithoutContextAsync();
    Console.ReadLine();
}
我以为上下文是Thread,但事实并非如此。
这里的上下文是SynchronizationContext. Await 会将延续(await 之后的其余方法)发布到当前上下文 ( SynchronizationContext.Current),如果它存在并且您没有使用ConfigureAwaitfalse。如果延续没有发布到上下文 - 它将在线程池线程上执行。在控制台应用程序中,默认情况下没有同步上下文,因此在您的测试ConfigureAwait中无效。您可以创建虚拟上下文来查看效果:
class MySynchornizationContext : SynchronizationContext {
    public override void Post(SendOrPostCallback d, object state) {
        Console.WriteLine("posted");
        base.Post(d, state);
    }
    public override void Send(SendOrPostCallback d, object state) {
        Console.WriteLine("sent");
        base.Send(d, state);
    }
}
然后在Main方法的开头:
SynchronizationContext.SetSynchronizationContext(new MySynchornizationContext());
有ConfigureAwait(true)(或根本没有) - 您将看到延续已发布到上下文(控制台中的“发布”行)。随着ConfigureAwait(false)- 你会看到它不是。
真正的同步上下文比当然更复杂。例如 UI 上下文(如在 winforms 或 WPF 中)将“排队”延续并在一个(UI)线程上执行它们。由于各种原因(并可能导致死锁),如您的问题引用中所述,这可能有问题,因此当您编写通用库时 - 使用ConfigureAwait(false以避免这种行为是有益的。
SynchronizationContext当然,不需要将所有回调发布到单个线程,它可以对它们做任何事情。例如 ASP.NET MVC 上下文(至少是旧版本)将回调发布到请求线程,并且可以有很多请求这么多请求线程。