I have been using async/await for a while, but delved deeper recently, and read a lot of best practice tips saying to by default always use ConfigureAwait(false) to prevent deadlocks and improve performance.
I just want to make sure I am not missing something when I presume this only applies when the is an actual current SynchronizationContext or TaskScheduler in play, correct?
If I have a Windows service app that is responding to messages/commands/etc. asynchronously, it always just uses the default scheduler = probably the same threadpool thread that the awaitable completed on will execute the continuation, thus no deadlock and no performance difference can be had from using ConfigureAwait(false), correct?
It's not like I can't put it there, but I hate noisey code so much...
In general, this is true. When working in a Console or Service scenario, there is no SynchronizationContext installed (by default) so the continueOnCapturedContext option in ConfigureAwait will have no effect, which means you can safely remove it without changing the runtime behavior.
However, there can be exceptions, so I would often suggest writing your code including ConfigureAwait(false) when appropriate anyways.
The main advantages of including this even in a console or service application are:
The code becomes reusable in other applications later. If you choose to reuse this code, you won't have to track down bugs that arise from not including this.
If you happen to install (or use a library that installs) a SynchronizationContext while running, the behavior of your methods won't change.
Related
I've been developing some library code that will be consumed by MVC action methods, so I've been reading a lot of Steven Cleary's blogs about the subject.
I ran in to his "Don't Block on Async Code" blog post, but am confused about some parts that seem contradictory.
Under "Preventing the Deadlock" he states:
There are two best practices (both covered in my intro post) that
avoid this situation:
In your “library” async methods, use ConfigureAwait(false) wherever
possible.
Don’t block on Tasks; use async all the way down.
Then later:
Using ConfigureAwait(false) to avoid deadlocks is a dangerous
practice. You would have to use ConfigureAwait(false) for every await
in the transitive closure of all methods called by the blocking code,
including all third- and second-party code. Using
ConfigureAwait(false) to avoid deadlock is at best just a hack).
Given these 2 statements, one saying that ConfigureAwait(false) is a best practice for library code, and one that says it is at best a dangerous hack, what is the actual proper way to write library code that won't deadlock when used in MVC?
I've read other question and answers on SO that might be considered duplicates of this, but none of them seem to address the contradictory information given by one of the experts on async / await.
The information isn't directly contradictory unless you take them out of context:
The former is general advice to writing library code; it's a good idea to do these things to make sure your library behaves well regardless of the synchronization context it's called in.
The latter is explicitly calling out how using ConfigureAwait(false) as a means to avoid a known deadlock scenario is a hack. It's saying,
I want to block here, but doing so would normally cause a deadlock, so I'll push the work to another thread (from the thread-pool) and hope everything works out okay.
If following the earlier advice to not block on tasks (use async all the way down), then this deadlock scenario won't happen.
The deadlock scenario is only relevant when running code within specific synchronization contexts which schedule continuations to execute on the thread which started the task, such as the one used by ASP.NET (a request is processed on one thread) or the one used by Windows desktop applications (a single thread for all UI events).
Blocking on the task in these contexts causes the single thread to block, so the thread is never free to run the continuation and the method deadlocks.
According to this article ASP.NET requires using the same SynchronizationContext for asynchronous operations in the controller, otherwise it blocks the running thread. As a conclusion author mentioned that we should use both the methods as the best practice to prevent threads deadlocks:
In your “library” async methods, use ConfigureAwait(false) wherever possible.
Don’t block on Tasks; use async all the way down.
Note: It is best to apply both best practices. Either one will prevent
the deadlock, but both must be applied to achieve maximum performance and responsiveness.
But what purpose led Microsoft to use the same SynchronizationContext? May be using of the ConfigureAwait(false), which disables the same sync context restriction, might lead to e.g. unpredictable behavior or performance issues. Thus, is it really good practice to use the ConfigureAwait(false) wherever is possible?
ASP.NET requires using the same SynchronizationContext for
asynchronous operations in the controller, otherwise it blocks the
running thread.
I'm not really sure what that statement means. ASP.NET doesn't require "the same" synchronization context. In order for you to be inside your HttpContext, you need that SynchronizationContext.
But what purpose led Microsoft to use the same SynchronizationContext?
I suggest you read It's All About SynchronizationContext to get the bigger picture about sync contexts. Basically, it's a mechanism which allows you to post continuations on a particular thread. It can be used, for example, to marshal work back onto the UI message loop thread inside UI applications.
May be using of the ConfigureAwait(false), which disables the same
sync context restriction, might lead to e.g. unpredictable behavior or
performance issues
On the contrary. Marshaling work back onto the sync context does have (very minimal) overhead, as the request needs to be posted (using the abstract SynchronizationContext.Post) back onto the desired thread and context. By using ConfigureAwait(false), you're saving that time and simply continuing execution on which ever thread was allocated.
Thus, is it really good practice to use the ConfigureAwait(false)
wherever is possible?
The primary reason to do that is to avoid deadlocks. When someone calling Task.Result or Task.Wait instead of asynchronously waiting using await, you get the classic deadlock scenario where the sync context is attempting to post the continuation back onto the thread, but it is currently blocked because Result and Wait are blocking calls. The other reason is the minor performance overhead you get.
Edit:
Why doesn't Microsoft encapsulate this method inside the Task class?
It looks like the ConfigureAwait(false) has just only the pluses. Is
there any minuses?
Let's image the following scenario: You execute a method which returns a Task and is awaited using await, and right after that you update some UI element. Now, what would be more natural to you? Would you prefer to implicitly return to the same "environment" you were before (the UI thread), or would you prefer that you had to explicitly specify that you want to return to that same environment?
I think that the former "feels" more natural to the user.
Example:
public Task FetchAndReturnAsync(string url)
{
var httpClient = new HttpClient();
return httpClient.GetAsync(url);
}
You call it like this:
var awesomeUiResult = await FetchAndReturnAsync("http://www.google.com");
textBox.Text = awesomeUiResult;
What do you think should happen? Is it more natural for you to be able to update the text box after the await, or for it to fail because you're now not inside your original context?
ASP.NET requires using the same SynchronizationContext for asynchronous operations in the controller, otherwise it blocks the running thread.
Sort of, but not quite. ASP.NET creates a SynchronizationContext for each incoming request, and this context is not tied to a specific thread at all. However, only one thread at a time can enter the context, so if a second thread attempts to enter it while one is already in it, then it will block that thread.
what purpose led Microsoft to use the same SynchronizationContext?
The SynchronizationContext for ASP.NET manages per-request data such as HttpContext.Current, culture, and user identity.
is it really good practice to use the ConfigureAwait(false) wherever is possible?
As a general rule, yes, especially for generic libraries. On ASP.NET, ConfigureAwait(false) doesn't gain you much - in some cases, a minor performance increase. It can be used to avoid the deadlock I mention in my article, but it's far better (especially on ASP.NET) to use async all the way.
I have a .NET 4.5.1 WCF service that handles synchronization from an app that will be used by thousands of users. I currently use Task.WaitAll as shown below and it works fine but I read that this is bad, can cause deadlocks, etc. I believe I tried WhenAll in the past and it didn't work, I don't recall the issues as I'm returning to this for review again just to make sure I'm doing this right. My concern is whether or not the blocking is needed and preferred in this use, a WCF service method hence why the WaitAll appears to work without issue.
I have about a dozen methods that each update an entity in Entity Framework 6 processing the incoming data with existing data and making the necessary changes. Each of these methods can be expensive so I would like to use parallelism mainly to get all methods working at the same time on this powerful 24 core server. Each method returns as Task as wraps its contents in Task.Run. The DoSync method created a new List and adds each of these sync methods to the list. I then call Task.WaitAll(taskList.ToArray()) and all works great.
Is this the right way of doing this? I want to make sure this method will scale well, not cause problems, and work properly in a WCF service scenario.
In high-scale services it is often a good idea to use async IO (which you are not - you use Task.Run). "High scale" is very loosely defined. The benefit of async IO on the server is that it does not block threads. This leads to less memory usage and less context switching. That is all there is to it.
If you do not need these benefits you can use sync IO and blocking all you like. Nothing bad will happen. Understand, that running 10 queries on background threads and waiting for them will temporarily block 11 threads. This might be fine, or not, depending on the number of concurrent operations you expect.
I suggest you do a little research regarding the scalability benefits of async IO so that you better understand when to use it. Remember that there is a cost to going async: Slower development and more concurrency bugs.
Understand, that async IO is different from just using the thread-pool (Task.Run). The thread-pool is not thread-less while async IO does not use any threads at all. Not even "invisible" threads managed by the runtime.
What I often find is: If you have to ask, you don't need it.
Task.WhenAll is the non-blocking equivalent of Task.WaitAll, and without seeing your code I can't think of any reason why it wouldn't work and wouldn't be preferable. But note that Task.WhenAll itself returns a Task which you must await. Did you do that?
I'm currently working on a largely asynchronous application which uses TAP throughout. Every class which has methods for spawning Tasks also has a TaskScheduler injected into it. This allows us to perform explicit scheduling of tasks, which as I understand, is not the way Microsoft are going with the Async CTP.
The only issue I have with the new approach (implicit scheduling) is that our previous philosophy has always been "we know the continuation will always specify their task scheduler, so we don't need to worry about what context we complete the task on".
Moving away from that does worry us slightly just because it has worked extremely well in terms of avoiding subtle threading errors, because for every bit of code we can see that the coder has remembered to consider what thread he's on. If they missed specifying the task scheduler, it's a bug.
Question 1: Can anyone reassure me that the implicit approach is a good idea? I see so many issues being introduced by ConfigureAwait(false) and explicit scheduling in legacy/third party code. How can I be sure my 'await-ridden' code is always running on the UI thread, for example?
Question 2: So, assuming we remove all TaskScheduler DI from our code and begin to use implicit scheduling, how do we then set the default task scheduler? What about changing scheduler midway through a method, just before awaiting an expensive method, and then setting it back again afterward?
(p.s. I have already read http://msmvps.com/blogs/jon_skeet/archive/2010/11/02/configuring-waiting.aspx)
I'll take a shot at answering. ;)
Question 1: Can anyone reassure me that the implicit approach is a good idea? I see so many issues being introduced by ConfigureAwait(false) and explicit scheduling in legacy/third party code. How can I be sure my 'await-ridden' code is always running on the UI thread, for example?
The rules for ConfigureAwait(false) are pretty simple: use it if the rest of your method can be run on the threadpool, and don't use it if the rest of your method must run in a given context (e.g., UI context).
Generally speaking, ConfigureAwait(false) should be used by library code, and not by UI-layer code (including UI-type layers such as ViewModels in MVVM). If the method is partially-background-computation and partially-UI-updates, then it should be split into two methods.
Question 2: So, assuming we remove all TaskScheduler DI from our code and begin to use implicit scheduling, how do we then set the default task scheduler?
async/await does not normally use TaskScheduler; they use a "scheduling context" concept. This is actually SynchronizationContext.Current, and falls back to TaskScheduler.Current only if there is no SynchronizationContext. Substituting your own scheduler can therefore be done using SynchronizationContext.SetSynchronizationContext. You can read more about SynchronizationContext in this MSDN article on the subject.
The default scheduling context should be what you need almost all of the time, which means you don't need to mess with it. I only change it when doing unit tests, or for Console programs / Win32 services.
What about changing scheduler midway through a method, just before awaiting an expensive method, and then setting it back again afterward?
If you want to do an expensive operation (presumably on the threadpool), then await the result of TaskEx.Run.
If you want to change the scheduler for other reasons (e.g., concurrency), then await the result of TaskFactory.StartNew.
In both of these cases, the method (or delegate) is run on the other scheduler, and then the rest of the method resumes in its regular context.
Ideally, you want each async method to exist within a single execution context. If there are different parts of the method that need different contexts, then split them up into different methods. The only exception to this rule is ConfigureAwait(false), which allows a method to start on an arbitrary context and then revert to the threadpool context for the remainder of its execution. ConfigureAwait(false) should be considered an optimization (that's on by default for library code), not as a design philosophy.
Here's some points from my "Thread is Dead" talk that I think may help you with your design:
Follow the Task-Based Asynchronous Pattern guidelines.
As your code base becomes more asynchronous, it will become more functional in nature (as opposed to traditionally object-oriented). This is normal and should be embraced.
As your code base becomes more asynchronous, shared-memory concurrency gradually evolves to message-passing concurrency (i.e., ConcurrentExclusiveSchedulerPair is the new ReaderWriterLock).
I'm porting a WPF app to WP7, and in the process I've had to refactor all the code that touches the network. The old code used the synchronous methods of the WebRequest object in background threads, but these methods no longer exist in WP7.
The result has been bewildering, and makes me feel like I'm doing something wrong. I've had to litter my views with thread dispatching code - the only alternative to this that I see is to supply the dispatcher to the lower tiers of the app, which would break platform-independence and muddy the boundary with the UI. I've lost the ability to make chained calls over the network from loops, and instead have callbacks invoking themselves. I've lost try/catch error handling and instead have OnSuccess and OnError callbacks everywhere. I'm now always unintentionally running code in background threads that are invoked by callbacks. I fondly remember the days when I was able to return values from methods.
I know continuation-passsing-style is supposed to be great, but I think all of the above has made the code more brittle and less readable, and has made threading issues more complex than they need to be.
Apologies if this question is vague, I'd just like to know if I'm missing some big picture here.
This is a limitation of Silverlight, which requires asynchronous network access (WCF proxy calls, WebClient, WebRequest, etc.). All synchronous network-reliant method calls have been removed from the framework.
To be crass: welcome to asynchronous programming. The only thing you did wrong was not making the calls asynchronous in the first place :)
I'm not 100% clear on the exact reasons MS removed the sync calls from web-dependent objects in Silverlight, but the explanations I hear always center on one or two reasons in some combination:
Browsers are architected on asynchronous network calls. Introducing synchronous calls would cause bad behavior/broken apps/crashes/etc.
If they gave everyone the "easy out" of making synchronous calls, the world would be littered with Silverlight apps that always froze while doing anything on the network, making Silverlight as a platform look bad.
That said - WCF proxies in Silverlight have the behavior that they always perform their callback on the calling thread. This is most often the UI thread, meaning you don't have to do any dispatching. I do not know if WebClient/WebRequest in Silverlight share this behavior.
As for the dispatcher, you could look into using a SynchronizationContext instead. The MVVM reference implementation in the MS Patterns and Practices Prism guidance does this - in the repository (data access class that actually makes calls out to an abstracted external service), they have a SynchronizationContext member that is initialized to System.Threading.SynchronizationContext.Current. This is the UI thread, if the constructor is called on the UI thread (it should be). All results from the service calls are then handled with mySynchronizationContext.Post.
Questions like this seem to behave like buses. You don't see any for ages then two come along almost at the same time. See this answer to a more concrete version of this question asked earlier today.
I have to I agree with you, continuation passing is tricky. A really useful technique is to borrow the C# yield return construct to create a machine that is able to maintain state between asynchronous operations. For a really good explanation see this blog by Jeremy Likness.
Personally I prefer a "less is more" approach so the AsyncOperationService is a very small chunk of code. You'll note that it has a single callback for both success and failure and there no interfaces to implement just a moderate delegate Action<Action<Exception>> which is typed as AsyncOperation to make it more convenient.
The basic steps to coding against this are:-
Code as if synchronous execution were possible
Create methods that return an AsyncOperation fpr only the smallest part that has to be asynchronous. Usually some WebRequest or WCF call but note just enough to get past the async bit, see me other answer for a good example.
Convert the synchronous "psuedo-code" to yeild these AsyncOperations and change the calling code to "Run" the resulting enumerable.
The final code looks quite similar to the synchronous code you might be more familar with.
As to accidentally running things on a background thread, that last answer included this useful AsyncOperation:-
public static AsyncOperation SwitchToUIThread()
{
return (completed => Deployment.Current.Dispatcher.BeginInvoke(() => completed(null)));
}
You can use that as the final yield in the run to ensure that code executing in the completed callback is executing on the UI thread. Its also useful to "flip" what is apparently synchronous code to be running on the UI thread when necessary.