【发布时间】:2018-08-26 02:05:16
【问题描述】:
我有下面的代码,它只是挂在 Task.WaitAll 行上。我猜这是由于死锁,其中主线程正在等待其同步上下文以继续执行,但其中一个延续也需要此上下文才能完成此处概述的执行:
http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
protected override async Task<Person> GetOrders()
{
var person = new Person();
var task1 = GetPersonOrders(person);
var task2 = GetPersonAddresses(person);
var tasks = new List<Task>(){task1, task2}
Task.WaitAll(tasks.ToArray());
}
public async Task GetPersonOrders(Person person)
{
...
person.PersonOrders = await GetPersonOrdersFromRepository();
}
public async Task<List<Order>> GetPersonOrdersFromRepository()
{
...
return await CallSomeWebService;
}
public async Task GetPersonAddresses(Person person)
{
...
person.Addresses = await GetPersonAddressesFromRepository();
}
public async Task<List<Address>> GetPersonAddressesFromRepository()
{
...
return await CallSomeWebService;
}
问题
1) 为什么将GetOrders()的final改为
await Task.WhenAll(tasks);
解决所有问题?为什么通过等待Task.WhenAll over Task.WaitAll解决了死锁?
2) 这些任务是否仍与 Task.WhenAll 修改并行运行?
【问题讨论】:
-
await进行协作多任务处理,而不是并行处理。await WhenAll配合调用者,WaitAll不仅不配合调用者,也不配合子任务。 -
其实...
WaitAll()需要手动启动任务吗?也许这就是这里的区别? -
@BenVoigt - 我删除了我的评论,因为是的,我认为这是不正确的。我有点不确定“多任务处理不是并行处理”是什么意思。一般来说,是的。但是,如果一个人按顺序启动两个真正的异步任务,我发现给定可用线程,它们会并行处理(每个都有自己的线程)。这个例子我错了吗?
-
@zzxyz:这取决于您运行的环境(特别是
TaskScheduler.Current实现。)即使GetPersonAddressesFromRepository和CallSomeWebService使用了其他线程(他们可能没有,因为 I/O 本质上是异步的),当你await他们一些TaskSchedulers 将尝试在同一个线程上执行其余的方法。这发生在 WPF、Windows 窗体和现代版本的 ASP.NET 等环境中。
标签: c# async-await