5

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?

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
ZunTzu
  • 7,244
  • 3
  • 31
  • 39

1 Answers1

5

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.

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
  • 2
    I disagree that people don't properly read the documentation in that particular case. The vast majority of the documentation is misleading and makes people believe there is nothing wrong with calling Task.Wait, Task.Result or the too many other different ways to shoot one's own foot. – ZunTzu Oct 26 '15 at 16:57
  • @ZunTzu By documentation I'm not only referring to MSDN. Just googling `Task.Wait` [brings up matches](http://stackoverflow.com/questions/13140523/await-vs-task-wait-deadlock) which explicitly tell you not to block on async code. More-over, learning about async-await requires experiment and reading, and there are many blog-post describing those deadlock scenarios exactly. It is the responsibility of the user to know what he's using and how it should be used. I *do agree* that the MSDN docs lack sufficient information regarding the dangerous of synchronously blocking on async operations. – Yuval Itzchakov Oct 26 '15 at 17:01
  • The documentation should be more explicit about the dangers, for instance the way it does for Thread.Abort. – ZunTzu Oct 26 '15 at 17:01
  • The link you posted is about Stephen Cleary explaining a deadlock issue regarding synchronization contexts. But that article is also misleading because not using synchronization contexts doesn't make Task.Wait safe. I challenge you to find an article about Task.Wait and thread pool starvation. – ZunTzu Oct 26 '15 at 17:11