等待vs Task.Wait – 死锁?

我不太了解Task.Waitawait之间的区别。

我有一些类似于ASP.NET WebAPI服务中的以下function:

 public class TestController : ApiController { public static async Task<string> Foo() { await Task.Delay(1).ConfigureAwait(false); return ""; } public async static Task<string> Bar() { return await Foo(); } public async static Task<string> Ros() { return await Bar(); } // GET api/test public IEnumerable<string> Get() { Task.WaitAll(Enumerable.Range(0, 10).Select(x => Ros()).ToArray()); return new string[] { "value1", "value2" }; // This will never execute } } 

哪里会死锁。

什么可能导致这个? 为什么当我使用阻塞等待而不是await Task.Delay时,这不会造成问题?

Waitawait – 而在概念上类似 – 实际上是完全不同的。

Wait将同步阻塞,直到任务完成。 所以当前的线程被封锁,等待任务完成。 作为一般规则,你应该使用“ async一路下来”; 也就是说,不要阻塞async代码。 在我的博客中,我详细讨论了如何在asynchronous代码中阻塞导致死锁 。

await将asynchronous等待,直到任务完成。 这意味着当前的方法是“暂停”(其状态被捕获),并且该方法向其调用者返回不完整的任务。 稍后,当awaitexpression完成时,该方法的其余部分被安排作为延续。

你还提到了一个“合作块”,我认为你的意思是你正在Wait的任务可以在等待的线程上执行。 有这种情况发生,但这是一个优化。 在很多情况下,这种情况是不可能发生的,例如,如果任务是针对另一个schedler,或者它已经启动,或者是非代码任务(例如在您的代码示例中: Wait不能内联执行Delay任务,因为没有代码)。

你可能会发现我的async / await介绍有帮助。