0

Using async/await as shown here http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html, one of the good practices is using ConfigureAwait(false) so the method return does not have to come back to the request context. What are the potential consequences of using this? Asked another way, when would this not be recommended?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
michael g
  • 103
  • 1
  • 12
  • UI components must be accessed on the thread that created them. – Daniel A. White Oct 09 '15 at 17:44
  • The linked article links to [another article](http://blog.stephencleary.com/2012/02/async-and-await.html) that may give you the answer you need. – Joshua Shearer Oct 09 '15 at 17:49
  • Keep in mind that the synchronization context doesn't necessarily mean a single thread. In say a winforms app it will, but in other contexts different posts can be run on different threads. You should think of it as running the code in a given context, not a given thread. – Servy Oct 09 '15 at 17:53
  • Thanks @JoshuaShearer, but the article's relevant portion leaves on this note: "A good rule of thumb is to use `ConfigureAwait(false)` unless you know you do need the context." From that, I would just like an example where we *do* need the context--thus making ConfigureAwait(false) inappropriate. – michael g Oct 09 '15 at 18:22

1 Answers1

3

when would this not be recommended?

Your method must return to the same context if there's code further down in the method that depends on that context. If the remainder of that method does not require a particular context, then it's a good practice to use ConfigureAwait(false).

There are two primary examples: UI code and ASP.NET code.

UI code must run on the UI thread; this includes most UI widget access, and I extend the definition of "UI code" to include my ViewModels as well (there are some situations in WPF where you can get away with updating the UI from a background thread, but that's not true for all MVVM platforms). So, if your method ends with a textBox1.Text = "" or a myViewModel.MyObservableCollection.Add(4), then it has to return to the UI thread before it can execute that code.

ASP.NET code must run in an ASP.NET request context; this includes any code that depends on HttpContext.Current (and many System.Web APIs implicitly assume an ASP.NET request context). So, if your method ends with HttpContext.Current.Items..., then it has to return to the ASP.NET request context before it can execute that code. (Side note: in ASP.NET vNext on .NET 4.6 and higher, the ASP.NET request context is actually going away).

In practice, what this means is that most library code should use ConfigureAwait(false), since well-written library code does not have a dependency on a particular UI framework or System.Web. Similarly, most application code should not use ConfigureAwait(false), since it has to update the UI / send an HTTP response.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • Thank you for such a great reply with examples. What about this case: I have two separate methods and a parent method that calls them both. The first calls an Async method and *returns* a Task. That Task is `await`ed on the parent method so that the result is returned. Finally, once returned, the result is ingested in the second method. How might contexts apply in this case? The method that calls the async method does not depend on the current context, but the parent method that actually `await`s the result does depend on the UI context. – michael g Oct 09 '15 at 18:46
  • 1
    @M.g.: The decision is made on a per-method basis. So, the child method(s) do not need the context and should use `ConfigureAwait(false)`. The parent method that does need the context should not use `ConfigureAwait(false)`. This is a normal pattern, with the methods further up the call stack representing more application-level concerns and the lower-level methods representing more library-like concerns. – Stephen Cleary Oct 09 '15 at 18:50
  • Ok. You're awesome. Thank you! – michael g Oct 09 '15 at 18:57
  • In using ConfigureAwait like so `return Client.GetAsync(URL).ConfigureAwait(false)` the return type becomes `System.Runtime.CompilerServices.ConfiguredTaskAwaitable` and according to the [docs](https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.configuredtaskawaitable(v=vs.110).aspx) I shouldn't be using this in code. So this leads me to question either [1] my design pattern or [2] whether I should be really using ConfigureAwait in this way. Any thoughts? @stephen – michael g Oct 10 '15 at 00:00
  • @M.g.: It's "ConfigureAwait", not "ConfigureTask". You should only use `ConfigureAwait` with `await`; if you're returning a task directly, just return the task. – Stephen Cleary Oct 10 '15 at 02:48
  • Wow, that was silly of me to get that mixed up. Thank you again! – michael g Oct 10 '15 at 20:19
  • @M.g.: It's actually fairly common - I think this makes the fourth time here on SO. Always in the comments, though, as a followup question. I may need to write a short blog post. :) – Stephen Cleary Oct 10 '15 at 21:28