What is the difference between await method(), await method().ConfigureAwait(true), and await method().ConfigureAwait(false) in C#?

I’m trying to understand the differences between the following three usages of the await keyword in C#:

  • await method();
  • await method().ConfigureAwait(true);
  • await method().ConfigureAwait(false);

From my research, I understand that it has something to do with how asynchronous continuations are handled, particularly in relation to synchronization contexts. However, I am still unclear on the exact differences and implications of each usage.

Could someone elaborate on:

What exactly happens in each case?
How does ConfigureAwait(true) differ from ConfigureAwait(false)?
When and why should one prefer ConfigureAwait(false) over the await method()?
Are there specific scenarios (e.g., UI applications vs. server applications) where one approach is recommended over the others?
Any detailed explanation or examples would be greatly appreciated!

6

In most cases you’re going to use async/await just as is.

Example: Console app (taken from the LinqPad examples):

async Task Main()
{
    "Starting".Dump();  
    int result = await myLongRunningTask();
    result.Dump();  
    "Finished".Dump();
}

async Task<int> myLongRunningTask()
{
    // Simulate an asynchronous operation that takes 3 seconds
    await Task.Delay (3000);
    return 42; // so long Douglas Adams, and thanks for all the books! :-)
}

Normally you would just use it like that. But if you have scenarios, where you have a good reason to use ConfigureAwait, there is a quite good description here describing what it does and what it can be used for.
Most of the following is taken from that FAQ to give you an idea, but please check out the link above, because there is much more:


Why would I want to use ConfigureAwait(false)?

When you perform an asynchronous operation using async and await, the operation is offloaded to a different thread or task, allowing the calling thread to continue executing other work. Once the asynchronous operation is complete, the rest of the async method (the continuation from the original context) needs to be executed.

ConfigureAwait(continueOnCapturedContext: false) is used to avoid forcing the callback to be invoked on the original context or scheduler. This has a few benefits:

Improving performance

There is a cost to queueing the callback rather than just invoking it, both because there’s extra work (and typically extra allocation) involved, but also because it means certain optimizations we’d otherwise like to employ in the runtime can’t be used (we can do more optimization when we know exactly how the callback will be invoked, but if it’s handed off to an arbitrary implementation of an abstraction, we can sometimes be limited).

Reliability benefits (avoiding deadlocks)

It can prevent deadlocks that are possible when the original context is blocked waiting for the task to complete, but the task is also waiting for the context to be free to continue.

Consider a library method that uses await on the result of some network download. You invoke this method and synchronously block waiting for it to complete, such as by using .Wait() or .Result or .GetAwaiter().GetResult() off of the returned Task object. Now consider what happens if your invocation of it happens when the current SynchronizationContext is one that limits the number of operations that can be running on it to 1, whether explicitly via something like the MaxConcurrencySynchronizationContext shown earlier, or implicitly by this being a context that only has one thread that can be used, e.g. a UI thread (the section Regarding “original context” below).

General-purpose library code

Code that is designed to be reused across different applications and is not specific to any particular application type (like a UI application). In such code, you typically don’t know or care about the synchronization context, so it’s safer and more efficient to use ConfigureAwait(false).

Why would I want to use ConfigureAwait(true)?

You wouldn’t, unless you were using it purely as an indication that you were purposefully not using ConfigureAwait(false) (e.g. to silence static analysis warnings or the like). ConfigureAwait(true) does nothing meaningful. When comparing await task with await task.ConfigureAwait(true), they’re functionally identical. If you see ConfigureAwait(true) in production code, you can delete it without ill effect.


In the simple example, instead of

     await Task.Delay(3000);

you could also write

     await Task.Delay(3000).ConfigureAwait(false);

but it will make no difference in a console application, because there is no synchronization context. To see and understand the impact, check out the section Regarding “original context” below.

However, it’s a good practice to use it in library code to avoid potential deadlocks and performance issues related to context capturing.

Please note that when you use ConfigureAwait(false), you must ensure that the code after the await does not need to run on the original context, such as updating the UI in a desktop application.


Regarding “original context”

“It is the SynchronizationContext instance that was captured at the await point, by reading the static SynchronizationContext.Current property. The async/await machinery captures automatically the context whenever an incomplete task is awaited, and invokes the continuation on the captured context.” – Theodor Zoulias

What “original context” means can be explained if you have a button on a WinForms application.
This example was chosen, because there you have one single UI Thread updating the application forms, buttons and other controls.

Windows Forms has a SynchronizationContext-derived type that overrides Post to do the equivalent of Control.BeginInvoke; that means any calls to its Post method will cause the delegate to be invoked at some later point on the thread associated with that relevant Control, aka “the UI thread” (described in more detail in the section What is a SynchronizationContext?).

The following click event handlers are doing something (here: a simple delay as implemented in myLongRunningTask()), and one of the buttons is using .ConfigureAwait(false), the other one not (using default behaviour which is equal to .ConfigureAwait(true)):

private async void BtnWithoutConfigureAwait_Click(object sender, EventArgs e)
{
    await myLongRunningTask().ConfigureAwait(false);
    // This line will throw an exception because it's not running on the UI thread
    lblResult.Text = "Completed without ConfigureAwait";
}

private async void BtnWithConfigureAwait_Click(object sender, EventArgs e)
{
    await myLongRunningTask(); // Implicitly ConfigureAwait(true)
    // This line will work fine because it's running on the UI thread
    lblResult.Text = "Completed with ConfigureAwait";
}

The button handler BtnWithConfigureAwait_Click works as expected, while the other one BtnWithoutConfigureAwait_Click will throw an exception, because the original context which is the UI thread of the application, is not available when continuing after the await (hence, lblResult.Text cannot be changed in that handler).

In the task myLongRunningTask() instead of a delay, you could think about any task that takes some time, such as a stored procedure running or a Mandelbrot picture rendering.

9

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật