【问题标题】:Should Task.Wait be deprecated?Task.Wait 应该被弃用吗?
【发布时间】:2015-10-28 05:52:29
【问题描述】:

我学到了从池线程调用 Task.Wait 会导致线程饥饿死锁的艰难方法。

根据this MSDN article,在“死锁”一章中,我们应该遵守这两条规则:

  • 不要创建其同步方法等待异步函数的任何类,因为可以从池中的线程调用此类。
  • 如果类阻塞等待异步函数,请勿在异步函数中使用任何类。

似乎唯一可以合法使用 Task.Wait 的地方是 Main 函数 - 我在这里有点夸张,但你明白了。

为什么 Task.Wait 仍然是 .NET 框架的一部分,看看它有多危险?

【问题讨论】:

    标签: c# .net asynchronous async-await task-parallel-library


    【解决方案1】:

    为什么 Task.Wait 仍然是 .NET 框架的一部分,看看如何 危险吗?

    因为您希望能够同步阻止Task。很少,但你仍然这样做。正如您所说,Main 可能是最流行(最好是唯一)会发生这种情况的地方。那个,以及微软因其向后兼容性而臭名昭著的事实,所以一旦引入它,它就不太可能被弃用或从 BCL 中消失。 Task.WaitAll 也是如此。

    真正的问题当人们没有正确阅读文档并且不理解调用这种方法的含义并最终滥用它时,IMO 就开始了。如果你小心使用它,它会做得很好。


    另一件事是你不能总是一直异步。不幸的是,很多时候您的代码是通过签名同步的,无法更改,需要调用异步方法调用。是的,这是危险的,所有人都气馁,被认为是anti-pattern with async code,我本人已经回答了至少十几个关于 SO 的问题,人们最终陷入僵局并且不明白为什么,但 TPL 作者仍然需要做出这些类型的调用是可能的。

    【讨论】:

    • 我不同意人们在特定情况下没有正确阅读文档。绝大多数文档都具有误导性,使人们相信调用 Task.Wait、Task.Result 或其他太多不同的方式来打自己的脚并没有错。
    • @ZunTzu 通过文档,我不仅指的是 MSDN。只需谷歌搜索Task.Waitbrings up matches,它明确告诉您不要阻塞异步代码。此外,学习 async-await 需要实验和阅读,并且有许多博客文章准确描述了这些死锁场景。用户有责任知道他正在使用什么以及应该如何使用它。我同意 MSDN 文档缺乏足够的信息来说明同步阻塞异步操作的危险。
    • 文档应该更明确地说明危险,例如它对 Thread.Abort 所做的方式。
    • 您发布的链接是关于 Stephen Cleary 解释有关同步上下文的死锁问题。但是那篇文章也具有误导性,因为不使用同步上下文并不能使 Task.Wait 安全。我挑战你找到一篇关于 Task.Wait 和线程池饥饿的文章。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-06
    • 1970-01-01
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多