Should Task.Wait be deprecated? - c#

I learnt the hard way that calling Task.Wait from a pool thread can lead to thread-starvation deadlock.
According to this MSDN article, in chapter 'deadlocks', we should obey these two rules:
Do not create any class whose synchronous methods wait for asynchronous functions, since this class could be called from a thread on the pool.
Do not use any class inside an asynchronous function if the class blocks waiting for asynchronous functions.
It seems the only place left for a legitimate use of Task.Wait is the Main function - I am exaggerating a bit here but you get the idea.
Why is Task.Wait still part of the .NET framework, seeing how dangerous it is?

Why is Task.Wait still part of the .NET framework, seeing how
dangerous it is?
Because you want to be able to synchronously block on a Task. Rarely, but you still do. As you said, Main is probably the most popular (and preferably the only) place where that would happen. That, and the fact that Microsoft is notorious for it's backwards compatability, so once this was introduced, it is highly unlikely to be deprecated or disappear from the BCL. Same goes for Task.WaitAll.
The real problem IMO starts when people don't properly read the documentation and don't understand the implications of calling such a method and end up misusing it. If you use it carefully, it does it's job great.
Another thing is the fact that you can't always go async all the way. Unfortunately, many times you have code, which is synchronous by signature, which can't be altered and needs to invoke an async method call. Yes, this is dangerous and discouraged by all and is considered an anti-pattern with async code, and I myself have answered at least a dozen question on SO where people end up deadlocking themselves and don't understand why, but the TPL authors still needed to make these type of calls possible.

Related

Why is writing ConfigureAwait(false) on every line with await always recommended and do I really need it?

The question is not about what ConfigureAwait does. But rather why literally everywhere I see something like
As a general rule, yes. ConfigureAwait(false) should be used for every await unless the method needs its context.
I.e. they propose that I should write
await Method1().ConfigureAwait(false);
await Method2().ConfigureAwait(false);
// Do something else
// ...
await Method3().ConfigureAwait(false);
await Method4().ConfigureAwait(false);
But in such case wouldn't be clearer just resetting context in the very beginning just once like
await Task.Yield().ConfigureAwait(false);
It guarantees that the code below will be executed with no sync context, doesn't it?
I.e. I read that writing ConfigureAwait once might not work if the method returns immediately.
And for me the obvious solution looks like call ConfigureAwait(false) on something that for sure doesn't return immediately, which Task.Yield is, right?
Also as I know the Task.Yield doesn't contain ConfigureAwait anymore(don't know why, as I know it used to have it before), but looking at the Task.Yield code it is pretty easy to write your own method which would do nothing more but calling the continuation with an empty sync context.
And for me it seems much much easier to read and especially to write when you write one time
await TaskUtility.ResetSyncContext();
than writing ConfigureAwait on every line.
Will that work(Task.Yield().ConfigureAwait(false) or similar custom method) or I miss something?
As a general rule, yes. ConfigureAwait(false) should be used for every await unless the method needs its context.
I've seen that advice often here on Stack Overflow, and it's even what Stephen Cleary (a Microsoft MVP) says in his Async and Await article:
A good rule of thumb is to use ConfigureAwait(false) unless you know you do need the context.
Stephen definitely knows his stuff, and I agree that the advice is technically accurate, but I've always thought that this is bad advice for two reasons:
Beginners, and
Maintenance risk
First, it's bad advice for beginners because synchronization context is a complex subject. If you start learning async/await by being told that "ConfigureAwait(false) should be used for every await unless the method needs its context", but you don't even know what "context" is and what it means to "need it", then you don't know when you shouldn't use it, so you end up always using it. That means you can run into bugs that will be very difficult to figure out unless you happen to learn that, yes, you did actually need that "context" thing and this magical "ConfigureAwait" thing made you lose it. You can lose hours trying to figure that out.
For applications of any kind, I believe the advice really should be the opposite: Don't use ConfigureAwait at all, unless you know what it does and you have determined that you absolutely don't need the context after that line.
However, determining you don't need the context can be either simple, or quite complex depending on what methods are called after. But even then - and this is the second reason I disagree with that advice - just because you don't need the context after that line right now, doesn't mean some code won't be added later that will use the context. You'll have to hope that whoever makes that change knows what ConfigureAwait(false) does, sees it, and removes it. Using ConfigureAwait(false) everywhere creates a maintenance risk.
This is what another Stephen, Stephen Toub (a Microsoft employee), recommends in the ConfigureAwait FAQ under the subheading "When should I use ConfigureAwait(false)?":
When writing applications, you generally want the default behavior (which is why it is the default behavior). ... This leads to the general guidance of: if you’re writing app-level code, do not use ConfigureAwait(false)
In my own application code, I don't bother trying to figure out where I can and can't use it. I just ignore that ConfigureAwait exists. Sure, there can be a performance improvement by using it where you can, but I really doubt that it will be a noticeable difference to any human, even if it is measurable by a timer. I don't believe the return on investment is positive.
The only exception to this is when you're writing libraries, as Stephen Toub points out in his article:
if you’re writing general-purpose library code, use ConfigureAwait(false)
That's for two reasons:
A library has no idea about the context of the application it's being used in, so it can't use the context anyway, and
If the person using the library decides to wait synchronously on your asynchronous library code, it could cause a deadlock that they cannot change because they can't change your code. (ideally, they shouldn't do that, but it can happen)
To address another point in your question: it's not always enough to use ConfigureAwait(false) on the first await and not the rest. Use it on every await in your library code. Stephen Toub's article under the heading "Is it ok to use ConfigureAwait(false) only on the first await in my method and not on the rest?" says, in part:
If the await task.ConfigureAwait(false) involves a task that’s already completed by the time it’s awaited (which is actually incredibly common), then the ConfigureAwait(false) will be meaningless, as the thread continues to execute code in the method after this and still in the same context that was there previously.
Edit: I finally got around to making this into an article on my site: Don’t use ConfigureAwait(false)

Contradictory advice regarding async / await in MVC

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.

Best solution for async chicken and egg story

I have been applying async best practices to all my libraries. Basically it means:
Only use async when it's truly async (libraries shouldn't lie)
Define a synchronous method if and only if you have a faster synchronous method that won’t dead lock.
Postfix all async methods with Async
I worked on a library that is synchronous by nature. This means it has only sync methods. If the user wants to run the work on a separate thread than the UI thread, they can do that themselves by using Task.Factory (responsibility of the caller).
However, inside a handler / method / extensibility point, we want to show the user a message box. This is an async method (for example, WinRT ShowDialogAsync). Then this gives us the following options:
A. Move everything to async (so we have the option to use await in our handlers and don't block anything).
public async Task MyMethodAsync()
{
await _messageService.ShowAsync();
}
The advantage is that users can add async methods without having to use .Wait(). The downside is that we are lying as a library (it's not truly async).
I have considered making everything async, but I don't think that's a good idea either. It would make all libraries lie but prepare them in case we would need it. Remember that making everything async out of the box has a (small) performance impact as well.
B. Inside the handler that requires user input, call .Wait()
public void MyMethod()
{
_messageService.ShowAsync().Wait();
}
The advantage is that this will allow us to use async code inside sync methods. But... it will never be callable from the UI-thread because the _messageService dispatches to the UI thread (but it cannot do that because it's still waiting for the method, resulting in a deadlock). This method will work when used inside a Task.Factory.Run block (but the responsibility is up to the end-user):
await Task.Factory.Run(() => MyMethod());
The question
I feel that both have pros and cons, but what would you choose? Let the library lie (A) or only allow the method to be called from a background thread (B)? Or maybe there are other options I've overseen.
If I go for A, it means I have to bump the major version every time (because it's actually a breaking change) whenever a user requests to convert a method to an async signature method.
Define a synchronous method if and only if you have a faster synchronous method that won’t dead lock.
I'd say "define a synchronous method if you have synchronous work to do". It doesn't matter how fast it is. The burden is on the caller to determine if it's too slow and they need to use Task.Run.
However, inside a handler / method / extensibility point
If this is an Observer kind of extensibility, consider just using events or observables.
However, it sounds like you want more of a Strategy kind of extensibility, where your invoking code must wait for and/or change its behavior based on the result of the callback.
I have considered making everything async, but I don't think that's a good idea either.
Async all the way is a guideline, not a strict command. It definitely applies in the 99% case, but this could be one of the exceptions. I would try not to make a library async just for the sake of a possibly-async Strategy pattern; I'd investigate other extension possibilities first. There is a valid argument for making the library async, if you view the Strategy callback as a dependency (the library would be async because its dependency is (possibly) async).
As you've discovered, there's no clean way to do sync-over-async. There are a few different hacks (such as blocking from a background thread), but you'll first need to decide whether you need to call your library from the UI thread.
If you do, then there's just two options: make the library async, or use a nested message loop. I strongly avoid nested message loops, especially in libraries; I'm just mentioning it for sake of completeness.
If you can impose on the user a requirement to only call the library from a non-UI thread, then you can apply other hacks. E.g., blocking the background thread.
There's not an easy solution, sorry.
As far as me personally... if the library needs an async Strategy, then I would lean towards making the library async. But it does depend on what kind of library it is, whether there were backwards-compatibility issues, etc. And the first thing I'd look into is a different kind of extensibility point.
as you can read here :
https://msdn.microsoft.com/en-us/magazine/jj991977.aspx
Async All the Way
Asynchronous code reminds me of the story of a fellow who mentioned that the world was suspended in space and was immediately challenged by an elderly lady claiming that the world rested on the back of a giant turtle. When the man enquired what the turtle was standing on, the lady replied, “You’re very clever, young man, but it’s turtles all the way down!” As you convert synchronous code to asynchronous code, you’ll find that it works best if asynchronous code calls and is called by other asynchronous code—all the way down (or “up,” if you prefer). Others have also noticed the spreading behavior of asynchronous programming and have called it “contagious” or compared it to a zombie virus. Whether turtles or zombies, it’s definitely true that asynchronous code tends to drive surrounding code to also be asynchronous. This behavior is inherent in all types of asynchronous programming, not just the new async/await keywords.
“Async all the way” means that you shouldn’t mix synchronous and asynchronous code without carefully considering the consequences. In particular, it’s usually a bad idea to block on async code by calling Task.Wait or Task.Result. This is an especially common problem for programmers who are “dipping their toes” into asynchronous programming, converting just a small part of their application and wrapping it in a synchronous API so the rest of the application is isolated from the changes. Unfortunately, they run into problems with deadlocks. After answering many async-related questions on the MSDN forums, Stack Overflow and e-mail, I can say this is by far the most-asked question by async newcomers once they learn the basics: “Why does my partially async code deadlock?”

Async CTP - Recommended approach for task scheduling

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).

WP7- Confused about network communication, cross thread access, and continuation passing

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.

Categories