2014-10-07 115 views
1

我一直在寻找一个解决方案,现在看来似乎必须是一个简单的问题。然而,我发现每一个例子创建的Task同样的情形这一个(从How to: Extend the Async Walkthrough by Using Task.WhenAll (C# and Visual Basic)页面上MSDN拍摄)集合:等待几种不同异步操作的结果使用Task.WhenAny

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

所以,我怎么能叫一些async方法和await使用Task.WhenAll方法的结果?

+0

什么是'GetTicketsAsync','GetGuestTicketsAsync'的返回类型..? – 2014-10-07 14:12:16

+0

'任务>' – Sheridan 2014-10-07 14:12:38

回答

7

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

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

+1感谢您的回复如此之快...虽然我不得不承认,尝试阅读您的回复时,您仍然每隔几秒钟更新一次,真的很痛苦......我会个人更喜欢等一会儿,并一口气读完,但也许我应该稍后再回来?无论哪种方式,您的解决方案似乎工作,所以谢谢。 – Sheridan 2014-10-07 14:33:43

+0

@Sheridan做任何适合你的工作。只要你回答人们可能有的澄清问题,你就可以在几小时后阅读。 – i3arnon 2014-10-07 14:36:10

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); 
+1

在这种情况下没有理由使用'Task.Run'。 – i3arnon 2014-10-07 14:24:00

+1

@ I3arnon尽管名称为“Async”,但我认为OP有同步方法。稍后在确认它是'任务'我更新了我的答案并删除了代码中的Task.Run。 – 2014-10-07 14:29:36

+1

+1是的,那是我的不好...我错误地回答了他的问题 - 对不起。 – Sheridan 2014-10-07 14:32:55