ConfigureAwait(false) tells await not to capture the current SynchronizationContext or TaskScheduler for its continuation. It does not mean “always switch threads”: completed tasks continue immediately on the current thread, and asynchronous work is not made background work merely by marking a method async. section 11.3 section 11.6
Use the continuation rules to choose deliberately:
- Preserve the default await behavior when subsequent code needs a UI thread, thread settings, or thread-local storage. section 11.7
- Use ConfigureAwait(false) when continuation code does not depend on the current context and should use the default task scheduler, normally the thread pool. section 11.6 section 11.7
- Do not assume a thread change: an already completed Task bypasses the continuation scheduling decision. section 11.3 section 11.6
Keep UI code on the UI thread
A WinForms event handler should normally await the operation and then update the control. Applying ConfigureAwait(false) to the handler continuation can move execution away from the UI thread, making `label1.Text = result` invalid. Keeping ConfigureAwait(false) inside the non-UI method allows that method to avoid the context while the handler resumes on the UI context. If every continuation deliberately avoids the context, marshal the update explicitly with `BeginInvoke`.
Listing 11.13 Deadlock prevented by using ConfigureAwait(false)
private void button1_Click(object sender, EventArgs ea)
{
var task = DoSomething();
label1.Text = task.Result;
}
private async Task<string> DoSomething()
{
await Task.Delay(500).ConfigureAwait(false); #1
return "done";
}
Inspect the complete deadlock example and the single ConfigureAwait(false) change that prevents the continuation from requiring the blocked UI context. section 11.3
