Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why would I bother to use Task.ConfigureAwait(continueOnCapturedContext: false);

Consider the following code of windows forms:

private async void UpdateUIControlClicked(object sender, EventArgs e) {     this.txtUIControl.Text = "I will be updated after await - i hope!";     await Task.Delay(5000).ConfigureAwait(continueOnCapturedContext: false);     this.txtUIControl.Text = "I am updated now."; } 

Here the exception is thrown at the 3rd line because after await the code is executed on non-UI thread. Where ConfigureAwait(false) is useful?

like image 924
Yawar Murtaza Avatar asked Jan 08 '15 22:01

Yawar Murtaza


People also ask

Why should I use ConfigureAwait false?

As a general rule, every piece of code that is not in a view model and/or that does not need to go back on the main thread should use ConfigureAwait false. This is simple, easy and can improve the performance of an application by freeing the UI thread for a little longer.

Should I use ConfigureAwait false .NET Core?

There are very few use cases for the use of ConfigureAwait(true), it does nothing meaningful actually. In 99% of the cases, you should use ConfigureAwait(false). In . NET Framework by default the Task execution will continue on the captured context, this is ConfigureAwait(true).

What is ConfigureAwait () used for?

ConfigureAwait in Action You capture the current context before awaiting the task, leaving it to the task context, then recovering (re-entering) it back when the task completes.

Should I use ConfigureAwait false everywhere?

No, you don't have to put ConfigureAwait everywhere in your library.


2 Answers

Stephen Cleary has a really good series on this you can find here, I quoted the piece specific to your question:

Most of the time, you don’t need to sync back to the “main” context. Most async methods will be designed with composition in mind: they await other operations, and each one represents an asynchronous operation itself (which can be composed by others). In this case, you want to tell the awaiter to not capture the current context by calling ConfigureAwait and passing false, e.g.:

private async Task DownloadFileAsync(string fileName) {   // Use HttpClient or whatever to download the file contents.   var fileContents = await DownloadFileContentsAsync(fileName).ConfigureAwait(false);    // Note that because of the ConfigureAwait(false), we are not on the original context here.   // Instead, we're running on the thread pool.    // Write the file contents out to a disk file.   await WriteToDiskAsync(fileName, fileContents).ConfigureAwait(false);    // The second call to ConfigureAwait(false) is not *required*, but it is Good Practice. }  // WinForms example (it works exactly the same for WPF). private async void DownloadFileButton_Click(object sender, EventArgs e) {   // Since we asynchronously wait, the UI thread is not blocked by the file download.   await DownloadFileAsync(fileNameTextBox.Text);    // Since we resume on the UI context, we can directly access UI elements.   resultTextBox.Text = "File downloaded!"; } 

The important thing to note with this example is that each “level” of async method calls has its own context. DownloadFileButton_Click started in the UI context, and called DownloadFileAsync. DownloadFileAsync also started in the UI context, but then stepped out of its context by calling ConfigureAwait(false). The rest of DownloadFileAsync runs in the thread pool context. However, when DownloadFileAsync completes and DownloadFileButton_Click resumes, it does resume in the UI context.

A good rule of thumb is to use ConfigureAwait(false) unless you know you do need the context.

like image 132
Victor Learned Avatar answered Oct 20 '22 12:10

Victor Learned


You should use it at all times in services since services should be UI agnostic.

However, dont use it outside of services if

  • need to manipulate UI or use UI specific components such as Dispatcher or CoreDispatcher
  • need to use HttpContext.Current in ASP.net

In these cases, you should not use ConfigureAwait(false) as it is important to capture current context otherwise app will crash with trying to access UI views from a non-UI thread

When you write await task;, that is equivalent to writing await task.ConfigureAwait(true);. So true is the default.

like image 25
pixel Avatar answered Oct 20 '22 11:10

pixel