等待vs Task.Wait – 死锁?
我不太了解Task.Wait
和await
之间的区别。
我有一些类似于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
时,这不会造成问题?
Wait
, await
– 而在概念上类似 – 实际上是完全不同的。
Wait
将同步阻塞,直到任务完成。 所以当前的线程被封锁,等待任务完成。 作为一般规则,你应该使用“ async
一路下来”; 也就是说,不要阻塞async
代码。 在我的博客中,我详细讨论了如何在asynchronous代码中阻塞导致死锁 。
await
将asynchronous等待,直到任务完成。 这意味着当前的方法是“暂停”(其状态被捕获),并且该方法向其调用者返回不完整的任务。 稍后,当await
expression完成时,该方法的其余部分被安排作为延续。
你还提到了一个“合作块”,我认为你的意思是你正在Wait
的任务可以在等待的线程上执行。 有这种情况发生,但这是一个优化。 在很多情况下,这种情况是不可能发生的,例如,如果任务是针对另一个schedler,或者它已经启动,或者是非代码任务(例如在您的代码示例中: Wait
不能内联执行Delay
任务,因为没有代码)。
你可能会发现我的async
/ await
介绍有帮助。