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.