async / await deadlock Task.WaitAll vs Task.WhenAll

时间:2018-03-16 22:28:41

标签: c# async-await

我有下面的代码,它只挂在Task.WaitAll行上。我猜这是由于一个死锁,其中主线程正在等待它的同步上下文继续执行但是其中一个延续也需要这个上下文以完成它的执行,如下所述:

http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

private boolean isViewOnScreen(RecyclerView rv, View view) {
    // Assuming a LinearLayoutManager but it could be another type.
    LinearLayoutManager lm = (LinearLayoutManager) recyclerView.getLayoutManager();
    int firstVisiblePosition = lm.findFirstVisibleItemPosition();
    int lastVisiblePosition = lm.findLastVisibleItemPosition();
    int viewPosition = lm.getPosition(view);
    return viewPosition >= firstVisiblePosition && viewPosition <= lastVisiblePosition;
}

问题

1)为什么要将GetOrders()的最终结果改为

 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;
}

解决所有问题?为什么等待Task.WhenAll over Task.WaitAll解决了死锁?

2)这些任务是否仍在与Task.WhenAll修改并行运行?

1 个答案:

答案 0 :(得分:2)

  

为什么将GetOrders()的最终更改为await Task.WhenAll(tasks);   解决一切?为什么等待Task.WhenAll over Task.WaitAll解决了死锁?

因为只要您点击awaitGetOrders()方法就会返回一个任务,表明它完成了所有可以同步执行的任务,其他任务可以接管此线程。< / p>

当您安排的任务从Web服务器,存储库等返回响应时,任务调度程序能够为任务&#39;分配线程。继续完成。

如果您在可以在并行同步上下文中完成这些任务的环境中运行它,那么即使使用Task.WaitAll(),您也不会遇到死锁。

同样,如果您始终在调用堆栈中使用每个 ConfigureAwait(false) await,那么您也不会遇到此问题,因为这会通知任务调度程序您不关心生成的任务是否继续在它开始的同一个同步上下文中。

  

这些任务是否仍在与Task.WhenAll修改并行运行?

没有。它们同时运行,但不是并行运行。

请记住,这个问题源于任务无法继续执行,直到它们启动的线程被释放。事实上,他们一次只允许在一个线程上运行,这意味着他们不会并行运行。

有关详细信息,请参阅What is the difference between asynchronous programming and multithreading?