使用Task.WhenAny等待几个不同的异步操作的结果

时间:2014-10-07 14:06:04

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

我现在一直在寻找解决方案,似乎必须是一个简单的问题。但是,我找到的每个示例都会创建一个与此类似的Task集合(取自MSDN上的How to: Extend the Async Walkthrough by Using Task.WhenAll (C# and Visual Basic)页面):

IEnumerable<Task<int>> downloadTasksQuery = 
    from url in urlList select ProcessURLAsync(url);

我无法执行此操作,因为我想调用不同的async方法和await结果...更像是这样的东西(但不是这样,因为这似乎没有任何东西):

var getTicketTasks = new List<Task<IEnumerable<ITicket>>>();
getTicketTasks.Add(new Task(() => Model.GetTicketsAsync(eventDate)));
getTicketTasks.Add(new Task(() => Model.GetGuestTicketsAsync(eventDate)));
...
getTicketTasks.Add(new Task(() => Model.GetOtherTicketsAsync(eventDate)));

IEnumerable<ITicket>[] tickets = await Task.WhenAll(getTicketTasks);

那么如何使用Task.WhenAll方法调用多个async方法和await结果?

2 个答案:

答案 0 :(得分:7)

不要使用该任务构造函数来调用异步方法*。只需调用这些方法,将返回的任务和await所有这些一起存储在Task.WhenAll中:

var getTicketTasks = new List<Task<IEnumerable<ITicket>>>();
getTicketTasks.Add(Model.GetTicketsAsync(eventDate));
getTicketTasks.Add(Model.GetGuestTicketsAsync(eventDate));
...
getTicketTasks.Add(Model.GetOtherTicketsAsync(eventDate));

IEnumerable<ITicket>[] tickets = await Task.WhenAll(getTicketTasks);

在您的情况下,您创建了一个任务,但是您没有启动它,因此它不会运行。如果你确实启动它,你只需触发实际的异步操作而不将返回的任务存储在任何地方。这意味着你没有await。您正在等待的所有任务都是开火并忘记了另一个async操作。

Task.WhenAll也有params的重载,因此另一个选项是:

var tickets = await Task.WhenAll(
    Model.GetTicketsAsync(eventDate),
    Model.GetGuestTicketsAsync(eventDate),
    Model.GetOtherTicketsAsync(eventDate));

*或在任何其他情况下。

答案 1 :(得分:2)

您刚刚创建了Task。你从来没有开始过它。通过其构造函数创建Task将不会启动Task,因此也不会转换为已完成状态。所以等待它将需要永远。

使用Task.Run或致电Task.Start但不建议拨打Task.Start。首选Task.Run启动异步操作。如果您已经有Task<T>,只需创建一个数组并等待它。

var getTicketTasks = new List<Task<IEnumerable<ITicket>>>();
getTicketTasks.Add(Model.GetTicketsAsync(eventDate));
getTicketTasks.Add(Model.GetGuestTicketsAsync(eventDate));
...
getTicketTasks.Add(Model.GetOtherTicketsAsync(eventDate));
IEnumerable<ITicket>[] tickets = await Task.WhenAll(getTicketTasks);